Search code examples
pythondjango-formsdjango-1.6

ModelForm requires user before one can be created: is_valid() returns false


I am attempting to create a custom user for a Django app and have run in to a slight problem that is proving time consuming. I will cut to the chase:

My version of Django is 1.6.2 and python 2.7.4

Here is the model

class Account(models.Model):
    user = models.OneToOneField(User)
    game_id = models.PositiveIntegerField(null=True, blank=True, default=None)
    avatar = models.ImageField()
    desc = models.CharField(max_length=2500, null=True, blank=True, default=None)

The ModelForm:

    class RegistrationForm(ModelForm):
        game_name = forms.CharField(label=(u'In Game Name'))
        email = forms.EmailField(label=(u'Email Address'))
        password = forms.CharField(label=(u'Password'), 
            widget=forms.PasswordInput(render_value=False))
        password1 = forms.CharField(label=(u'Verify Password'), 
            widget=forms.PasswordInput(render_value=False))

        class Meta:
            model = Account
            exclude = ('user',)

        def clean_game_name(self):
            username = self.cleaned_data['game_name']
            try:
                User.objects.get(username=username)
            except User.DoesNotExist:
                return username
            raise forms.ValidationError("That username is already taken, please select another.")

        def clean(self):
            if self.cleaned_data['password'] != self.cleaned_data['password1']:
                raise forms.ValidationError("The passwords did not match.  Please try again.")
            return self.cleaned_data

And the View:

def account_registration(request):
    if request.user.is_authenticated():
        return HttpResponseRedirect('/account/profile/')
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid(): # returns false
            user = User.objects.create_user(
                username=form.cleaned_data['game_name'],
                email=form.cleaned_data['email'],
                password=form.cleaned_data['password'])
            user.save()
            member = Account(user=user)
            member.save()
            return HttpResponseRedirect('/account/profile/')
        else:
            print form.errors # output below
            return render_to_response('account/register.html', {'form': form}, context_instance=RequestContext(request))
    else:
        form = RegistrationForm()
        context = {'form': form}
        return render_to_response('account/register.html', context, context_instance=RequestContext(request))

Output of print:

user: This field is required. 

How can I supply the RegistrationForm with a User object that should not exist until after the registration form has validated? I am brand new to both python and django so I assume that the solution is pretty obvious.

EDIT: adding the template

<form action="" method="post">
{% csrf_token %}
{% if form.errors %}<p>Please correct the following fields:</p>{% endif %}
<div class="register_div">
        {% if form.game_name.errors %}<p class="error">{{ form.game_name.errors }}</p>{% endif %}
        <p><label for="game_name"{% if form.game_name.errors %} class="error"{% endif %}>In Game Name:</label></p>
        <p>{{ form.game_name }}</p>
</div>
<div class="register_div">
        {% if form.email.errors %}<p class="error">{{ form.email.errors }}</p>{% endif %}
        <p><label for="email"{% if form.email.errors %} class="error"{% endif %}>Email:</label></p>
        <p>{{ form.email }}</p>
</div>
<div class="register_div">
        {% if form.password.errors %}<p class="error">{{ form.password.errors }}</p>{% endif %}
        <p><label for="password"{% if form.password.errors %} class="error"{% endif %}>Password:</label></p>
        <p>{{ form.password }}</p>
</div>
<div class="register_div">
        {% if form.password1.errors %}<p class="error">{{ form.password1.errors }}</p>{% endif %}
        <p><label for="password1"{% if form.password1.errors %} class="error"{% endif %}>Verify Password:</label></p>
        <p>{{ form.password1 }}</p>
</div>
<p><input type="submit" alt="register" /></p>
</form>

Solution

  • As I mentioned in the comment, there's no reason for this to be a ModelField on Account at all. Although you are creating an Account within the valid clause, you don't actually do it from any of the fields in the form itself. You should make this a normal form (inherit from forms.Form and drop the Meta class): the rest of the code stays exactly the same, and the User and Account instances will still be created.

    That said, I'm still not sure why that code should be giving that error. You have excluded the User field, so it should not be requiring it for the form to be valid.