Как получить доступ к данным, когда form.is_valid () имеет значение false - PullRequest
47 голосов
/ 09 апреля 2009

Когда у меня есть действующая форма Django, я могу получить доступ к данным с помощью form.cleaned_data. Но как мне получить данные, введенные пользователем, когда форма недействительна, то есть form.is_valid имеет значение false.

Я пытаюсь получить доступ к формам в наборе форм, поэтому form.data, кажется, просто напутает.

Ответы [ 7 ]

42 голосов
/ 17 сентября 2009

Вы можете использовать

form.data['field_name']

Таким образом вы получаете необработанное значение, присвоенное полю.

17 голосов
/ 09 апреля 2009

См. http://docs.djangoproject.com/en/dev/ref/forms/validation/#ref-forms-validation

Во-вторых, как только мы решили, что объединенные данные в двух полях мы рассматриваем не действительны, мы должны не забудьте удалить их из cleaned_data.

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

Исходные данные всегда доступны в request.POST.


Комментарий предполагает, что смысл состоит в том, чтобы сделать что-то вроде более сложной проверки на уровне поля.

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

В каждом поле можно выполнить любой вид проверки исходного содержимого.

13 голосов
/ 13 июня 2012

Я боролся с подобной проблемой и натолкнулся на отличную дискуссию: https://code.djangoproject.com/ticket/10427

Это не совсем хорошо задокументировано, но для живой формы вы можете просмотреть значение поля - как видят виджеты / пользователи - со следующим:

form_name['field_name'].value()
8 голосов
/ 07 июля 2015

У меня много методов. Все, что вы можете выбрать.

Полагаю, что форма похожа на приведенную ниже:

class SignupForm(forms.Form):
    email = forms.CharField(label='email')
    password = forms.CharField(label='password',
                               widget=forms.PasswordInput)

1-1. Получите от request

def signup(req):
    if req.method == 'POST':
        email = req.POST.get('email', '')
        password = req.POST.get('password', '')

2-1. Получите raw value, присвоенный полю и верните значение атрибута data поля

def signup(req):
    if req.method == 'POST':
        ...
        sf = SignupForm(req.POST)
        email = sf["email"].data
        password = sf["password"].data
        ...

2-2. Получить необработанное значение, присвоенное полю, и вернуть значение атрибута value поля

def signup(req):
    if req.method == 'POST':
        ...
        sf = SignupForm(req.POST)
        email = sf["email"].value()
        password = sf["password"].value()
        ...

2-3. Получите dictionary, присвоенный полям

def signup(req):
    if req.method == 'POST':
        ...
        sf = SignupForm(req.POST)
        # print sf.data
        # <QueryDict: {u'csrfmiddlewaretoken': [u'U0M9skekfcZiyk0DhlLVV1HssoLD6SGv'], u'password': [u''], u'email': [u'hello']}>
        email = sf.data.get("email", '')
        password = sf.data.get("password", '')
        ...
5 голосов
/ 27 мая 2011

Вы можете использовать этот шаблон:

class MyForm(forms.Form):
    ...
    def clean(self):
        self.saved_data=self.cleaned_data
        return self.cleaned_data

В вашем коде:

if form.is_valid():
    form.save()
    return django.http.HttpResponseRedirect(...)
if form.is_bound:
    form.saved_data['....'] # cleaned_data does not exist any more, but saved_data does.

Использование form.data не является хорошим решением. Причины:

  • Если форма имеет префикс, то словарные ключи будут иметь префикс этого префикса.
  • Данные в form.data не очищаются: есть только строковые значения.
3 голосов
/ 21 марта 2012

Я столкнулся с подобной проблемой, используя formset. В моем примере я хотел, чтобы пользователь выбрал 1-й вариант перед вторым, но если при 1-м выборе произошла другая ошибка, также отображалась ошибка «1-й выбор до 2-го».

Чтобы получить неочищенные данные 1-го поля, я использовал их в чистом методе поля формы:

dirty_rc1 = self.data[self.prefix + '-reg_choice_1']

Затем я могу проверить наличие данных в этом поле:

if not dirty_rc1:
    raise ValidationError('Make a first choice before second')

Надеюсь, это поможет!

1 голос
/ 17 августа 2009

Вы получаете доступ к данным либо из метода clean () поля, либо из метода clean () формы. clean () - это функция, которая определяет, является ли форма действительной или нет. Он вызывается, когда вызывается is_valid (). В форме clean () у вас есть список cleaned_data, когда вы можете запустить пользовательский код, чтобы убедиться, что он все проверен. В виджете у вас также есть clean (), но он использует единственную переданную переменную. Чтобы получить доступ к методу clean (), вам нужно создать его подкласс. e.g.:

class BlankIntField(forms.IntegerField):
    def clean(self, value):
        if not value:
            value = 0
        return int(value)

Если вы хотите, например, IntField, который не задыхается от пустого значения, используйте вышеприведенное.

clean () на форме работает примерно так:

def clean(self):
    if self.cleaned_data.get('total',-1) <= 0.0:
        raise forms.ValidationError("'Total must be positive")
    return self.cleaned_data

Также у вас может быть функция clean_FIELD () для каждого поля, чтобы вы могли проверять каждое поле отдельно (после вызова поля clean ())

...