Django ModelForms - "экземпляр" не работает должным образом

У меня есть форма модели, которая будет либо создавать новую модель, либо редактировать существующую - это просто и должно работать, но по какой-то причине я каждый раз получаю новый экземпляр.

Сценарий - это первый шаг в заказе электронной коммерции. Пользователь должен заполнить некоторую информацию, описывающую порядок (которая хранится в модели). Я создаю модель, сохраняю ее, затем перенаправляю к следующему представлению, чтобы пользователь мог ввести свою информацию cc. Я вставляю модель в сеанс, поэтому мне не нужно выполнять поиск в БД в следующем представлении. В шаблоне есть ссылка для второго (информация cc) вида, которая позволяет пользователю вернуться к первому виду для редактирования своего заказа.

# forms.py

class MyForm(forms.ModelForm):
    class Meta:
        fields = ('field1', 'field2')
        model = MyModel

# views.py

def create_or_update(request):
    if request.method == 'POST':
        form = MyForm(request.POST)
        if form.is_valid():
            m = form.save(commit=False)
            # update some other fields that aren't in the form
            m.field3 = 'blah'
            m.field4 = 'blah'
            m.save()
            request.session['m'] = m
            return HttpResponseRedirect(reverse('enter_cc_info'))
        # invalid form, render template
        ...
    else:
        # check to see if we're coming back to edit an existing model
        # this part works, I get an instance as expected
        m = request.session.get('m', None)
        if m:
            instance = get_object_or_None(MyModel, id=m.id)
            if instance:
                form = MyForm(instance=instance)
            else:
                # can't find it in the DB, but it's in the session
                form = MyForm({'field1': m.field1, 'field2': m.field2})
        else:
            form = MyForm()

    # render the form
    ...

Если я перейду в отладчик, когда вернусь к представлению, чтобы отредактировать заказ, форма будет создана с экземпляром, установленным в ранее созданную модель, как и ожидалось. Однако, когда форма обрабатывается в последующем POST, она создает новый экземпляр модели при вызове form.save().

Я полагаю, что это потому, что я ограничил поля в форме, поэтому в отрендеренном HTML нет нигде, чтобы сохранить идентификатор (или другую ссылку) в существующей модели. Тем не менее, я попытался добавить поля "pk" и "id" (не одновременно), но тогда моя форма не отображается вообще.

Я подозреваю, что я делаю это более сложным, чем нужно, но я застрял на данный момент и мог бы использовать некоторые отзывы. Заранее спасибо.

1 ответ

Решение

Это интересно. Вот мой удар в этом. Рассмотрим эту строку:

form = MyForm(request.POST)

Можете ли вы проверить содержимое request.POST? В частности, проверьте, есть ли какая-либо информация относительно того, какой экземпляр модели редактируется. Вы найдете, что нет ни одного. Другими словами, каждый раз, когда вы сохраняете форму на POST новый экземпляр будет создан.

Почему это происходит? Когда вы создаете форму, передавая instance=instance Аргумент ключевого слова. Вы говорите классу Form возвращать экземпляр для экземпляра модели. Однако, когда вы отображаете форму в шаблоне, эта информация используется только для заполнения полей. То есть информация о конкретном экземпляре теряется. Естественно, когда вы публикуете пакет, есть способ подключиться к старому экземпляру.

Как вы можете предотвратить это? Распространенной идиомой является использование первичного ключа как части URL и поиск экземпляра на POST, Затем создайте форму. В вашем случае это будет означать:

def create_or_update(request, instance_id):
#                             ^^^^^ 
#                             URL param
    if request.method == 'POST':
        instance = get_object_or_None(Model, pk = instance_id)
        # ^^^^^
        # Look up the instance

        form = MyForm(request.POST, instance = instance)
        #                           ^^^^^^^
        #                           pass the instance now.
        if form.is_valid():
              ....
Другие вопросы по тегам