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

17

Из исходного кода вы можете видеть, что класс Form класса Django 1.4 имеет свойство 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() .

    
задан Ghopper21 29.07.2012 в 18:22
источник
  • отличная возможность. Спасибо за объяснение. ;-) –  Houman 02.08.2012 в 00:08

3 ответа

23

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

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

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

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

ответ дан Ghopper21 14.08.2012 в 16:12
  • Любой шанс вы можете расширить, как использовать начальное ключевое слово. Используете ли вы его при отправке формы или используете ее, когда форма возвращается? И как это работает с экземпляром? –  Sevenearths 20.10.2013 в 17:23
  • @ Ghopper21 вы могли бы предоставить фрагмент кода? –  andilabs 13.02.2014 в 15:07
5

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

  1. Вы также передаете исходные данные dict конструктору формы во время почтовых запросов.
  2. Вы не используете поля с show_hidden_initial=True . (Проблема с такими полями заключается в том, что пользователь может представить начальное значение, используемое для сравнения, и, следовательно, оно не будет заслуживающим доверия.)
ответ дан Florian Apolloner 05.08.2012 в 17:09
  • спасибо! Этот ответ требует другого вопроса для меня - что такое show_hidden_initial? Я не могу найти его в документах Django ... –  Ghopper21 05.08.2012 в 18:04
  • show_hidden_initial означает, что второе скрытое поле создается вместе с исходным выходом html, который содержит начальное значение поля. –  Florian Apolloner 05.08.2012 в 22:02
  • Я вижу, спасибо. –  Ghopper21 05.08.2012 в 22:53
0

Вот фрагмент кода, который делает то, что предлагает @ 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
    
ответ дан Roozbehan 31.05.2017 в 09:03