Подтвердить что ты не робот

В Django 1.4 do Form.has_changed() и Form.changed_data, которые недокументированы, работают должным образом?

Из исходного кода вы можете видеть, что класс Django 1.4 Form имеет метод has_changed() и свойство changed_data, которые кажутся весьма полезными, но недокументированы. Мой вопрос: выполняйте эти работы, как ожидалось, т.е.:

  • В Form.clean(), Form.has_changed() возвращает True, если какие-либо данные формы были изменены, в противном случае False
  • В Form.clean(), Form.changed_data - список имен полей, значения которых изменены.

Если да, есть ли какие-либо конкретные причины не использовать их, кроме обычных оговорок/опасностей об использовании недокументированных функций (т.е. подлежит изменению, не поддерживаться и т.д.)?

ПРИМЕЧАНИЕ 1. Для работы с пользовательскими виджетами эти виджеты должны иметь метод _has_changed(), который определен для встроенных виджетов.

ПРИМЕЧАНИЕ 2. Интересно, что документация включает в себя необоснованное упоминание метода Formset.has_changed(), но не Form.has_changed().

4b9b3361

Ответ 1

После изучения источника Django, с полезными подсказками из ответа Флориана, я могу сообщить, что has_changed и changed_data работают, как описано в моем вопросе, если форма имеет способ получить исходные данные для сравнения новые данные против.

Итак, вопрос в том, как форма, созданная из данных POST, знает, каковы начальные значения формы GET? Короткий ответ - нет, если вы не скажете это каким-то образом. Это можно сделать двумя способами:

  • С помощью аргумента ключевого слова initial в форму и/или аргументы ключевого слова initial для полей точно так же, как вы указываете форме GET начальные значения. ПРИМЕЧАНИЕ. Если вы сделаете это, вам следует убедиться, что вы используете те же значения для своих форм GET и POST. Это единственный действительно надежный способ сделать это, поскольку вы непосредственно контролируете исходные значения.

  • Вы позволяете Django выполнять работу по запоминанию начальных значений из вашего GET, устанавливая аргумент ключевого слова show_hidden_initial для True для каждого применимого поля. Для этих полей Django отображает скрытый элемент ввода с исходным значением в форму GET HTML. Позже, когда вы вызываете has_changed или changed_data в форме POST, для любого поля с show_hidden_initial как True Django автоматически получает начальные значения из скрытых входных элементов в данных POST (заменяя любые начальные значения из initial формы или аргументы поля). ПРИМЕЧАНИЕ. Как и все, что полагается на данные POST, этот подход в конечном счете ненадежен, поскольку значения для скрытых входов все равно могут быть изменены, несмотря на то, что они скрыты.

Ответ 2

Вы можете полагаться на эти методы в двух условиях:

  • Вы также передаете исходные данные dict конструктору формы во время почтовых запросов.
  • Вы не используете поля с show_hidden_initial=True. (Проблема с такими полями заключается в том, что пользователь может представить начальное значение, используемое для сравнения, и, следовательно, оно не будет заслуживающим доверия.)

Ответ 3

Вот фрагмент кода, который делает то, что предлагает @Ghopper21. Чтобы получить исходные данные, я использую функцию values ​​() в QueryDict. Он возвращает словарь, содержащий данные, принадлежащие этому объекту. Важным моментом является то, что я не проверял, как он обрабатывает ссылки на внешние ключи.

saveStudentView(request,studentID):
    existingData = Student.objects.filter(id=paperID).values()[0]
    form = StudentForm(request.POST)
    if form.is_valid():
        form = StudentForm(request.POST, initial=existingData)
        if not form.has_changed():
            //Tell the user nothing has changed
        else:
            //Do other stuff