#django #django-forms
#django #django-forms
Вопрос:
У меня есть поле ModelForm, основанное на следующей модели:
class Phrase(models.Model):
subject = models.ForeignKey(Entity) # Entity is unique on a per Entity.name basis
object = models.ForeignKey(Entity) # Entity is unique on a per Entity.name basis
В modelform (PhraseForm) есть поле ‘subject’, которое является символьным полем. Я хочу, чтобы пользователи могли вводить строку. Когда modelform сохраняется, а строка не соответствует существующему объекту, создается новый объект.
Вот почему мне пришлось перезаписать поле «subject» формы модели, поскольку я не могу использовать автоматически сгенерированное поле «subject» формы модели (надеюсь, я здесь ясно выражаюсь).
Теперь все тесты выполняются нормально при создании новой фразы через modelform. Но при изменении фразы:
p = Phrase.objects.latest()
pf = PhraseForm({'subject': 'anewsubject'}, instance=p).
pf.is_valid() возвращает False. Ошибка, которую я получаю, заключается в том, что «объект» не может быть None. Это имеет смысл, поскольку поле объекта действительно не было заполнено.
Каков был бы наилучший способ справиться с этим? Я мог бы, конечно, проверить, предоставлен ли экземпляр в функции init() фразеформы, а затем присвоить отсутствующие значения полей из переданного экземпляра. Мне кажется, что это неправильный способ, так есть ли менее громоздкий способ убедиться, что данные экземпляра передаются через ModelForm?
Теперь, когда я набираю это, я предполагаю, что это не так, поскольку базовые поля модели перезаписываются, что означает, что значения полей формы должны быть заполнены снова, чтобы все работало нормально. Что заставляет меня перефразировать мой вопрос: является ли способ, которым я разрешил пользователям вводить произвольный текст и связывать это с новым или существующим объектом, правильным способом сделать это?
Заранее спасибо!
Ответ №1:
Почему вы изменяете форму с помощью.
p = Phrase.objects.latest()
p.subject = Entity.objects.get_or_create(name='anewsubject')[0]
Если вы действительно используете форму, она должна работать нормально:
def mod_phrase(request, phrase_id=None):
phrase = get_object_or_404(Phrase, pk=phrase_id)
if request.method == 'POST':
form = PhraseForm(request.POST, instance=phrase)
if form.is_valid():
form.save()
return HttpResponse("Success")
else:
form = PhraseForm(instance=phrase)
context = { 'form': form }
return render_to_response('modify-phrase.html', context,
context_instance=RequestContext(request))
Установка экземпляра для ModelForm задает исходные данные, а также позволяет форме узнать, с каким объектом работает форма. То, как вы пытаетесь использовать форму, вы передаете недопустимый data
словарь (отсутствуют object
), о котором форма правильно сообщает вам, что он недействителен. Когда вы устанавливаете data
значение request.POST
в request.POST
приведенном выше примере, в него включаются исходные данные, которые позволяют форме проверять правильность.
Комментарии:
1. Ах, черт. Перечитав это, я понимаю, что форма, естественно, ожидает данных для всех полей. Мне следовало сделать перерыв, прежде чем публиковать свой запутанный вопрос… (Кстати, я использую get_or_create, но внутри формы, чтобы преобразовать пользовательский ввод в новую или существующую сущность).