I am unable to get the choice field to validate on creating users. it doesn't make sense at all.

687 views
Skip to first unread message

sashank reddy

unread,
Mar 19, 2014, 11:40:18 AM3/19/14
to django...@googlegroups.com
Hi,

I have been trying to extend the UserCreationForm and have a form which performs user registration and adds email and the names.
In addition I am using a choice field that allows a list down of existing groups so that you can assign the user to an group immediately  upon creation.

The problem is that, if I create a new group, and try to add users to it, then the form validation fails.
I have restart the django server or wait for it to reset internally and show "Validating models ..". Then it starts to work.

The following is the code snippet:
=============================================================================
def choice_desig():
choice_desig = []
g = Group.objects.all()
for k in g:
choice_desig.append((k.name, k.name))
return choice_desig

class New_user_form(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
desig_group = forms.ChoiceField(choices=choice_desig())

def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.email = self.cleaned_data["email"]
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
designation = self.cleaned_data["desig_group"]
if commit:
user.save()
p = person.objects.get(pk=employee_id)
u = user_maps(user_name=user.username, emp_id=p)
u.save()
g = Group.objects.filter(name=designation)
print("acquired group", g[0].name)
#user.groups.add(g)
g[0].user_set.add(user)
g[0].save()
return user

def register_user(request):
if request.method == 'POST':
print("Register user : POST")
print("request.POST = ", request.POST)
form = New_user_form(request.POST)
if form.is_valid():
print("Form Validated")
new_user = form.save()
context = {}
print_user(new_user)
host = request.get_host()
link = "http://"+host +"/hr_base/index"
#return HttpResponseRedirect("http://"+host +"/hr_base/index")
return HttpResponseRedirect("/hr_base/index")
else:
print("Forms non field error", form.non_field_errors())
print("Form invalid")
print("choice_desig = ",choice_desig())
emp_id = request.POST.get('emp_id')
#host = request.get_host()
#link = "http://"+host +"/hr_base/index"
#return HttpResponseRedirect("http://"+host +"/hr_base/index")
return HttpResponseRedirect("/emp_users/new_user")
else:
print("Non post method")
print("Acquired emp_id: ", request.session['emp_id'])
form = New_user_form()
#form.acquire_groups()
#print("Form desig choice : ", form.choice_desig)
g = Group.objects.all()
desig = []
for k in g:
desig.append(k.name)
args = {}
args.update(csrf(request))
args.update({'user':request.user.username,
'form':form,
'STATIC_URL':settings.STATIC_URL,
'is_user_authenticated': request.user.is_authenticated(),
'is_user_superuser':request.user.is_superuser,
'desig': desig,})
res= render_to_response('emp_users/register.html', args)
return res

print("general area")
return HttpResponse("Doesn't Make sense")
===========================================================================================
Below is the template:
==========================================================================================
<h2>Register</h2>
<hr />
<form action='/emp_users/new_user' method='post'>{% csrf_token %}
<table>
<tr>
<th><label for="id_username">Username:</label></th>
<td>
<input id="id_username" maxlength="30" name="username" type="text" />
<br /><span class="helptext">Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.</span>
</td>
</tr>
<tr>
<th><label for="id_password1">Password:</label></th>
<td>
<input id="id_password1" maxlength="4096" name="password1" type="password" />
</td>
</tr>
<tr>
<th><label for="id_password2">Password confirmation:</label></th>
<td>
<input id="id_password2" maxlength="4096" name="password2" type="password" />
<br /><span class="helptext">Enter the same password as above, for verification.</span>
</td>
</tr>
<tr>
<th><label for="id_email">email</label></th>
<td>
<input id="id_email" maxlength="4096" name="email" type="email" />
<br /><span class="helptext">Enter your email id, for verification.</span>
</td>
</tr>
<tr>
<th><label for="id_first_name">First name:</label></th>
<td>
<input id="id_first_name" maxlength="4096" name="first_name" type="text" />
</td>
</tr>
<tr>
<th><label for="id_last_name">Last name:</label></th>
<td>
<input id="id_last_name" maxlength="4096" name="last_name" type="text" />
</td>
</tr>
<tr>
<th><label for="id_desig_group">Group/Designation:</label></th>
<td>
<select id="id_desig_group" name="desig_group">
{% for i in desig %}
<option value='{{ i }}'>{{ i }}</option>
{% endfor %}
</select>
</td>
</tr>
</table>
<input type="submit" value="Register"/>
</form>
========================================================================================

I did some debugging on my own and I was surprised.
The validation error is for the select field desig_group and it fails somewhere just after self.validate(value) in the field.clean method.
The prints clearly indicate that the method passed and completed.

def validate(self, value):
        print("Validating. value = ", value, "Empty validator result = ", value in validators.EMPTY_VALUES, "self.required = ", self.required)
        if value in validators.EMPTY_VALUES and self.required:
            print("validating: empty values =", validators.EMPTY_VALUES)
            print("validating: self.required =", self.required)
            raise ValidationError(self.error_messages['required'])
        print("Validation complete")
def clean(self, value):
        """
        Validates the given value and returns its "cleaned" value as an
        appropriate Python object.

        Raises ValidationError for any errors.
        """
        print("Field cleaning")
        value = self.to_python(value)
        print("Field got value by to_python :", value)
        self.validate(value)
        print("Field executing validators : ")
        self.run_validators(value)
        print("Completed executing field validator")
        return value

For these prints, I got this in my console:
=============================================
BaseForm: _clean_fields: cleaning
BaseForm: _clean_fields: Got widget value :  tester90
BaseForm: _clean_fields: isinstance else
Field cleaning
Field got value by to_python : tester90
Validating. value =  tester90 Empty validator result =  False self.required =  True
Validation complete
BaseForm: _clean_fields: ValidationError for  desig_group
==================================================

That is ridiculous as the next statement after Validation complete is  print("Field executing validators : ") which should have been printed.

I need to solve this to be able to bring stability to my application. Please help.

Regards,
Preetam

Tom Evans

unread,
Mar 19, 2014, 12:13:39 PM3/19/14
to django...@googlegroups.com
If you use choice_desig() function like that, it will get called once,
when the server initially parses that file. It will never be run again
until the server re-parses that file.

You could pass a callable to choices - "choices=choice_desig".

However, the right solution for when you want a form field to choose a
model instance is to use a form.ModelChoiceField.

Cheers

Tom

sashank reddy

unread,
Mar 19, 2014, 12:41:52 PM3/19/14
to django...@googlegroups.com, teva...@googlemail.com

Hi Tom,

What do you mean callable?
I tried changing
desig_group = forms.ChoiceField(choices=choice_desig()) 
to
desig_group = forms.ChoiceField(choices=choice_desig)

It gave error 'function' object is not iterable
But I want to know if the following would work.

desig = forms.ModelChoiceField(queryset=Group.objects.all())

But how do I change my view and template for it.
Can you please correct my view and template.

Regards,
Preetam

sashank reddy

unread,
Mar 20, 2014, 6:12:15 AM3/20/14
to django...@googlegroups.com, teva...@googlemail.com
Hi Tom,

I have not understood what you have said. Shouldn't choice_desig be called every time I instantiate it in the view with the form = New_user_form(). I thought I was creating an object of New_user_form every time I do that.

Regards,
Preetam

Tom Evans

unread,
Mar 20, 2014, 7:42:07 AM3/20/14
to sashank reddy, django...@googlegroups.com
On Thu, Mar 20, 2014 at 10:12 AM, sashank reddy
<preetamsa...@gmail.com> wrote:
> Hi Tom,
>
> I have not understood what you have said. Shouldn't choice_desig be called
> every time I instantiate it in the view with the form = New_user_form(). I
> thought I was creating an object of New_user_form every time I do that.

This is pretty basic python, the function is run when python
interprets the class.

Eg,

class Foo(object):
some_var = 'this is a string'.split()

The string is split only once, when the class Foo is parsed by python,
not whenever an instance of Foo is instantiated. Things that happen
when an instance is instantiated are contained in the __init__ method.

Although the some_var looks like it is just declaring a class
attribute, it is actually just running code in the scope of the class,
and as such you can write almost any code there (contrast with
definition of class variables in java). Eg this is perfectly valid:

class Foo(object):
some_var = 'this is a string'.split()
some_var = some_var[1:]
some_var.sort()


Cheers

Tom

sashank reddy

unread,
Mar 20, 2014, 1:41:24 PM3/20/14
to django...@googlegroups.com, sashank reddy, teva...@googlemail.com
Hi Tom,

I did try an override meanwhile.

I added,

def initialize_designation(self):
print("Initializing designation")
self.desig_group = forms.ChoiceField(choices=choice_des())
return
to my form class.
This will override the desig_group that is previously declared.
I call this in the view after the form instance is created and assigned to form
form.initialize_designation()
I am getting the prints from the function meaning that the function is executed.
Still there is Validation error.

This should have worked right? Why dint this work?

Regards,
Preetam

sashank reddy

unread,
Mar 20, 2014, 2:50:51 PM3/20/14
to django...@googlegroups.com, sashank reddy, teva...@googlemail.com
Tom,

In addition it still doesn't explain why I am unable to traceback the point of exception.
How can there be an exception when the only thing there are are few perfect prints

I am always invariably getting the

"Validation completed print" 

for desig_name field.
Then I get

"BaseForm: _clean_fields: ValidationError for  desig_group"

It should actually be:
"
Field executing validators :
Running validators
Completed executing field validator"

It should atleast give the first 2 prints
The following are the prints in my core files Field class in django.forms.fields:
========================================================
    def validate(self, value):
        if value in validators.EMPTY_VALUES and self.required:
            raise ValidationError(self.error_messages['required'])
        print("Validation complete")

    def run_validators(self, value):
        print("Running validators")
        if value in validators.EMPTY_VALUES:
            return
        errors = []
        for v in self.validators:
            try:
                v(value)
            except ValidationError as e:
                if hasattr(e, 'code') and e.code in self.error_messages:
                    message = self.error_messages[e.code]
                    if e.params:
                        message = message % e.params
                    errors.append(message)
                else:
                    errors.extend(e.messages)
        if errors:
            raise ValidationError(errors)

    def clean(self, value):
        """
        Validates the given value and returns its "cleaned" value as an
        appropriate Python object.

        Raises ValidationError for any errors.
        """
        value = self.to_python(value)
        self.validate(value)
        print("Field executing validators : ")
        self.run_validators(value)
        print("Completed executing field validator")
        return value

sashank reddy

unread,
Mar 21, 2014, 7:55:57 AM3/21/14
to django...@googlegroups.com, sashank reddy, teva...@googlemail.com
Hi Tom,

As per your first suggestion I tried a ModelChoiceField in place of ChoiceField.
It also results in a validation error.
I am putting my new code here.
=================================================================================
class New_user_form(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
#desig_group = forms.ChoiceField(choices=choices_des_fn())
desig_group = forms.ModelChoiceField(queryset=Group.objects.all())

def initialize_designation(self):
print("Initializing designation")
self.desig_group = forms.ChoiceField(choices=choice_des())
return

def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.email = self.cleaned_data["email"]
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
designation = self.cleaned_data["desig_group"]
print("New_user_form save : Designation :", designation)
if commit:
user.save()
g = Group.objects.filter(name=designation)
print("acquired group", g[0].name)
#user.groups.add(g)
g[0].user_set.add(user)
g[0].save()
return user

def register_user(request):
if request.method == 'POST':
print("Register user : POST")
print("request.POST = ", request.POST)
form = New_user_form(request.POST)
valid = form.is_valid()
print("validation complete. result = ", valid)
if valid:
print("Form Validated")
new_user = form.save()
context = {}
return HttpResponseRedirect("/hr_base/index")
else:
print("Forms non field error", form.non_field_errors())
print("Form invalid")
print("choice_desig = ",choice_desig())
print("validation error. retrying")
else:
print("Non post method")
form = New_user_form()
g = Group.objects.all()
desig = []
for k in g:
desig.append(k.name)
args = {}
args.update(csrf(request))
args.update({'user':request.user.username,
'form':form,
'STATIC_URL':settings.STATIC_URL,
'is_hr_group':hr_group(request.user),
'is_user_authenticated': request.user.is_authenticated(),
'is_user_superuser':request.user.is_superuser,
'desig': desig,
'k': zip(desig, range(len(desig))),
})
res= render_to_response('emp_users/register.html', args)
return res
===========================================================================================
Given below is my template
===========================================================================================
{% for i,j in k %}
<option value='{{ j }}'>{{ i }}</option>
{% endfor %}
</select>
</td>
</tr>
</table>
<input type="submit" value="Register"/>
</form>
==================================================================================
Whats going wrong here?
Am I missing something here?
I am not getting much info anywhere on ChoiceFields or ModelChoiceFields  with dynamic data.

Regards,
Preetam
Reply all
Reply to author
Forward
0 new messages