CodyBugstein
CodyBugstein

Reputation: 23322

Django subclass (model) not implementing attributes of superclass

I created a model for my website's users:

class ImrayWebsiteUser(models.Model):
    user = models.OneToOneField(User) 
    score = models.IntegerField(default=0)   
    birthDate = models.DateField(null=True,blank=True)
    clubs = models.ManyToManyField(Club)

In Views, I created a page for new users to register. When they click register (after filling the form) I created another View that checks a form and saves the users data if it's valid.

Here's the View:

def register_user(request):
    if request.method == 'POST':
        form = MyRegistrationForm(request.POST)
        if form.is_valid():
            form.save() #save user registeration data
            return HttpResponseRedirect('/accounts/register_success') 

    # in the first time it generate empty form:
    args = {}
    args.update(csrf(request))

    args['form'] = MyRegistrationForm()

    return render_to_response('accounts/register.html', args)

And the form:

class MyRegistrationForm(UserCreationForm):
    email = forms.EmailField(required=True)
    first_name = forms.CharField(required=False,max_length=30)
    last_name = forms.CharField(required=False,max_length=30)

    class Meta:
        model = ImrayWebsiteUser
        fields = ('username', 'email', 'password1', 'password2',
                  'first_name', 'last_name')

    def save(self, commit=True):
        user = super(MyRegistrationForm, self).save(commit=False)
        user.email = self.cleaned_data['email']
        user.firstname = self.cleaned_data['first_name']
        user.lastname = self.cleaned_data['last_name']
        # user.set_password(self.cleaned_data['password1'])

        if commit:
            user.save()

        return user

The problem is, when I fill in the form information, and click register (thus executing the View and sending the data to the form) I get an AttributeError saying that ImrayWebsiteUser has no attribute called set_password. This shouldn't happen though, since my user ImrayWebsiteUser clearly implements the built in User type.

This is the error code:

AttributeError at /accounts/register/
'ImrayWebsiteUser' object has no attribute 'set_password'
Request Method: POST
Request URL:    http://127.0.0.1:8000/accounts/register/
Django Version: 1.5
Exception Type: AttributeError
Exception Value:    
'ImrayWebsiteUser' object has no attribute 'set_password'
Exception Location: C:\Python27\lib\site-packages\django\contrib\auth\forms.py in save, line 107
Python Executable:  C:\Python27\python.exe
Python Version: 2.7.6
Python Path:    
['C:\\Users\\Imray\\ImraySite\\bitbucket',
 'C:\\Python27\\lib\\site-packages\\setuptools-2.1-py2.7.egg',
 'C:\\Windows\\SYSTEM32\\python27.zip',
 'C:\\Python27\\DLLs',
 'C:\\Python27\\lib',
 'C:\\Python27\\lib\\plat-win',
 'C:\\Python27\\lib\\lib-tk',
 'C:\\Python27',
 'C:\\Python27\\lib\\site-packages']
Server time:    Thu, 13 Mar 2014 11:56:27 +0200

Upvotes: 0

Views: 564

Answers (1)

sagarchalise
sagarchalise

Reputation: 1020

Your OnetoOneField is not implementation of User model.

https://docs.djangoproject.com/en/1.6/ref/models/fields/#ref-onetoone

You can access OneToOneField as object.user attribute in your case.

Since you are using inbuilt UserCreationForm which implements set_password, you can create a method in your model called set_password and call self.user.set_password

But I recommend you look into custom user implementation:

https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#auth-custom-user

EDIT: This is just a concept according to what I got from your question:

class UserProfile(models.Model):
  user = models.OneToOneField(User)
  .....your other attributes

also for RegistrationForm you could do something like:

class MyRegistrationForm(UserCreationForm):
  ....your registration form attributes from UserProfile Model
  class Meta:
    fields = ('username', 'email', 'firstname', 'lastname')  # fields of User Model not your UserProfile Model

  def save(self, commit=True):
     user = super(MyRegistrationForm, self).save(commit=commit)
     userprofile = UserProfile(user=user)
     userprofile.attribute = form.cleaned_data[attribute_name]...
     return user|userprofile #as required

Also csrf is already available in template as {% csrf_token %}

Upvotes: 1

Related Questions