Wednesday, June 29, 2011

Django Form not printing out error messages

forms.AuthenticationForm(request.POST) is WRONG, it will not give the wanted error messages (e.g. shown when username and password don't match, when users forget to put in a password).

forms.AuthenticationForm(data=request.POST)


details are highlighted:

[09:38am] haoqili: in python, is it true that if one argument has "name=" in front, the rest of the arguments need to have that too?
[09:38am] haoqili: as in
[09:38am] cvan: no, as long in they are in the correct order
[09:38am] haoqili: "forms.AuthenticationForm(data=request.POST, only_active=True)" is valid
[09:38am] haoqili: oh
[09:38am] cvan: but it is good practice to do that
[09:38am] haoqili: "forms.AuthenticationForm(request.POST, only_active=True)" is not
[09:38am] cvan: so "data=" is not needed
[09:38am] cvan: because it's the first argument
[09:39am] cvan: but it's good practice to either consistenly always used named arguments
[09:39am] cvan: or don't use any names
[09:41am] haoqili: cvan
[09:41am] haoqili: this is really interesting
[09:41am] haoqili: so
[09:41am] haoqili: form = forms.AuthenticationForm(data=request.POST or None, only_active=True)
[09:41am] haoqili: works
[09:42am] haoqili: form = forms.AuthenticationForm(request.POST or None, only_active=True)
[09:42am] haoqili: does not work
[09:42am] haoqili: :P
[09:42am] haoqili: and you are right, "only_active=True" is the culprit
[09:42am] haoqili: :D
[09:43am] cvan: that doesnt make sense if the first works but the second doesnt
[09:44am] cvan: because 'data' is the first argument for forms
[09:44am] cvan: def __init__(self, data=None,
[09:44am] cvan: from the django source for Form
[09:45am] haoqili: hmm
[09:45am] haoqili: that's strange
[09:45am] cvan: are you sure it's not being only_active wasnt True?
[09:45am] cvan: because in what you pasted, only_active is iin both of them
[09:46am] haoqili: oh so the first thing I pasted gives out the intended error messages
[09:46am] haoqili: but the second one was like what we had yesterday, no error messages
[09:46am] haoqili: let me try the 1st one without only_active
[09:47am] haoqili: :O
[09:47am] haoqili: :O
[09:47am] haoqili: So
[09:47am] haoqili: it narrows down to
[09:48am] haoqili: "form = forms.AuthenticationForm(request.POST or None)" does NOT give our wanted error messages
[09:48am] cvan: okay but "only_active" does?
[09:48am] haoqili: "form = forms.AuthenticationForm(data=request.POST or None)" does
[09:48am] haoqili: !!
[09:48am] cvan: weeeird
[09:48am] haoqili: LOL
[09:48am] haoqili: do you want me to come up so you can look more into this?
[09:48am] cvan: because that is the first argument, unless AuthenticationForm does something weird
[09:48am] haoqili: this is sooo strange
[09:48am] cvan: one second let me look at the source for AuthenticationForm again
[09:48am] haoqili: ok
[09:48am] cvan: but stick with "data" named arguments for now, of course
[09:49am] cvan: AAAH
[09:49am] cvan: it's not the first argument for AuthenticationForm
[09:49am] cvan: they override it
[09:49am] haoqili: !!
[09:49am] cvan: that's why!
[09:50am] cvan: silly silly
[09:50am] haoqili: where is this file your looking at?
[09:50am] cvan: because for forms.Form, the first argument is 'data'

# src/django/django/contrib/auth/forms.py line 69

def __init__(self, request=None, *args, **kwargs):

[09:50am] cvan: that's why! request is the first argument for AuthenticationForm
[09:50am] cvan: so as you can see, it really helps to use named arguments ;)
[09:50am] cvan: or just look at the source
[09:51am] cvan: tricky, tricky
[09:51am] haoqili: :O
[09:51am] haoqili: so in the regular "django forms" data is the first argument?
[09:51am] cvan: yep
[09:52am] cvan: but this AuthenticationForm inherits django's Form class
[09:52am] cvan: and extends it
[09:52am] cvan: so that's why it was confusing
[09:53am] haoqili: where is django's Form class?
[09:53am] haoqili: I can't find "from django import forms"
[09:53am] haoqili: oh I found it
[09:54am] cvan: cool

# from src/django/django/forms/forms.py line 72

class BaseForm(StrAndUnicode):
      # This is the main implementation of all the Form logic. Note that this
      # class is different than Form. See the comments by the Form class for more
      # information. Any improvements to the form API should be made to *this*
      # class, not to the Form class.
      def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,

[09:55am] haoqili: that's the structure that you had in mind, right?
[09:55am] cvan: yep :)
[09:55am] haoqili: I'm so glad we figured this out!!
[09:55am] cvan: yep, good job :)

No comments:

Post a Comment