Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AbstractUser Django full example

I am new to Django and I have been trying this for weeks, but could not find a way to solve this problem.

I want to store additional information like user mobile number, bank name, bank account. And want to store the mobile number while user registers and wants user to login with either (mobile number and password) or (email and password).

This is my UserProfile model

from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser
# Create your models here.

class UserProfile(AbstractUser):

     user_mobile = models.IntegerField(max_length=10, null=True)
     user_bank_name=models.CharField(max_length=100,null=True)
     user_bank_account_number=models.CharField(max_length=50, null=True)
     user_bank_ifsc_code = models.CharField(max_length=30,null=True)
     user_byt_balance = models.IntegerField(max_length=20, null=True)

And this is my forms.py

from django import forms            
from django.contrib.auth.models import User   # fill in custom user info then save it 
from django.contrib.auth.forms import UserCreationForm      
from models import UserProfile
from django.contrib.auth import get_user_model

class MyRegistrationForm(UserCreationForm):
    email = forms.EmailField(required = True)
    mobile = forms.IntegerField(required=True)



    class Meta:
        model = UserProfile
        fields = ('username', 'email', 'password1', 'password2','mobile' )        

    def save(self,commit = False):   
        user = super(MyRegistrationForm, self).save(commit = False)
        user.email = self.cleaned_data['email']
        user.user_mobile = self.cleaned_data['mobile']
        user.set_password(self.cleaned_data["password1"])

        user_default = User.objects.create_user(self.cleaned_data['username'],
                                                self.cleaned_data['email'],
                                                self.cleaned_data['password1'])
        user_default.save()

        if commit:
             user.save()

         return user

In my settings.py I have included

AUTH_USER_MODEL = "registration.UserProfile"

admin.py of my app is

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from models import UserProfile

class UserProfileInline(admin.StackedInline):
    model = UserProfile
    can_delete = False
    verbose_name_plural = 'userprofile'

 class UserProfileAdmin(UserAdmin):
    inlines = (UserProfileInline, )

 admin.site.register(UserProfile, UserProfileAdmin)

While adding the user from admin I get this error

Exception at /admin/registration/userprofile/1/
<class 'registration.models.UserProfile'> has no ForeignKey to <class 'registration.models.UserProfile'>

Can someone help me with this or point out to the full working exapmle, I have seen Django documentation but didn't find any luck. Or if there is another way to do this.

Thanks in advance

Edit 1:

While registering from the registration form I'm also getting this error

DatabaseError at /register
(1146, "Table 'django_auth_db.auth_user' doesn't exist")
like image 632
vaibhav1312 Avatar asked Feb 14 '14 12:02

vaibhav1312


People also ask

What is AbstractUser in Django?

AbstractUser class inherits the User class and is used to add Additional Fields required for your User in Database itself. SO its change the schema of the database. It is basically used to add fields like date_of_birth , location and bio etc. to the existing User model This is Done to the very Beginning of the project.

How do I override a User model in Django?

All you have to do is add AUTH_USER_MODEL to settings with path to custom user class, which extends either AbstractBaseUser (more customizable version) or AbstractUser (more or less old User class you can extend).

Should you create custom User model in Django?

It's highly recommended to set up a custom User model when starting a new Django project. Without it, you will need to create another model (like UserProfile ) and link it to the Django User model with a OneToOneField if you want to add new fields to the User model.


2 Answers

You have confused yourself a bit here. The idea of subclassing AbstractUser - and defining AUTH_USER_MODEL as your subclass - is that the new model completely replaces auth.models.User. You shouldn't be importing the original User at all, and you certainly should be calling User.objects.create_user(): your new model's manager now has its own create_user method.

Because of this, there's no reason to muck about with inline admins. Your UserProfile should be registered in the admin using the existing django.contrib.auth.admin.UserAdmin class.

like image 146
Daniel Roseman Avatar answered Oct 11 '22 07:10

Daniel Roseman


Inlines forms assume that you have a Generic ForeignKey on your model, in this case, the UserProfileAdmin expect a Generic ForeignKey of the UserProfile, that does not exists. Try to do a regular Model Admin, like:

class UserProfileAdmin(admin.ModelAdmin):
    can_delete = False
    verbose_name_plural = 'userprofile'

admin.site.register(UserProfile, UserProfileAdmin)
like image 26
Fabiano Moraes Avatar answered Oct 11 '22 07:10

Fabiano Moraes