Django ModelForms - «экземпляр» не работает должным образом - PullRequest
3 голосов
/ 06 октября 2010

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

Сценарий - это первый шаг в заказе электронной коммерции. Пользователь должен заполнить некоторую информацию, описывающую порядок (которая хранится в модели). Я создаю модель, сохраняю ее, затем перенаправляю к следующему представлению, чтобы пользователь мог ввести свою информацию 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 Ответ

9 голосов
/ 06 октября 2010

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

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():
              ....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...