Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom user model in django 1.5

Tags:

django

I have extended the django 1.5 user model as below and i am having problems when i insert any row into the database. My models.py file looks like below.

class MyUserManager(BaseUserManager):

   def create_user(self, email, password=None):

     if not email:
        raise ValueError('Users must have an email address')

     user = self.model(
        email=MyUserManager.normalize_email(email),
     )

     user.set_password(password)
     user.save(using=self._db)
     return user

   def create_superuser(self, email, password):

     user = self.create_user(email,
        password=password
     )
     user.is_admin = True
     user.save(using=self._db)
     return user


 class MyUser(AbstractBaseUser):
    email = models.EmailField(
      verbose_name='Email address',
      max_length=255,
      unique=True,
      db_index=True,
    )
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'

    def get_full_name(self):
      # The user is identified by their email address
      return self.email

    def __unicode__(self):
      return self.email

And my admin.py looks like below.

class MyUserAdmin(UserAdmin):
   # The forms to add and change user instances
   form = UserChangeForm
   add_form = UserCreationForm

   # The fields to be used in displaying the User model.
   # These override the definitions on the base UserAdmin
   # that reference specific fields on auth.User.
   list_display = ('email', 'is_admin')
   list_filter = ('is_admin',)
   fieldsets = (
     (None, {'fields': ('email', 'password')}),
     ('Permissions', {'fields': ('is_admin',)}),
     ('Important dates', {'fields': ('last_login',)}),
   )
   add_fieldsets = (
     (None, {
         'classes': ('wide',),
         'fields': ('email', 'password1', 'password2')}
     ),
   )
   search_fields = ('email',)
   ordering = ('email',)
   filter_horizontal = ()

// Now register the new UserAdmin...
admin.site.register(MyUser, MyUserAdmin)
// ... and, since we're not using Django's builtin permissions,
// unregister the Group model from admin.
admin.site.unregister(Group)

I followed the above from the django tutorial (https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example)

Now the problem i am having is whenever i modify anything in the admin, i am getting an error message saying below.

(1452, 'Cannot add or update a child row: a foreign key constraint fails (csiop.django_admin_log, CONSTRAINT user_id_refs_id_c8665aa FOREIGN KEY (user_id) REFERENCES auth_user (id))')

So, it looks like django_admin_log table always needs foreign key reference to auth_user model. But because i created a customer user model, when i create a super user the user details are only stored in the customer MyUser table and no entry gets created in the auth_user model, which seems to be causing the issue.

How do i solve this issue ? Please suggest.

Thanks Sreekanth

like image 896
Dev Avatar asked Mar 31 '13 15:03

Dev


People also ask

What is custom user model in Django?

The default User model in Django uses a username to uniquely identify a user during authentication. If you'd rather use an email address, you'll need to create a custom User model by either subclassing AbstractUser or AbstractBaseUser .

How do I change my auth model in Django?

In short, you can use the get_user_model() method to get the model directly, or if you need to create a ForeignKey or other database relationship to the user model, use settings. AUTH_USER_MODEL (which is simply a string corresponding to the appname.


2 Answers

This looks very much like a (PostgreSQL) database error - not a Django error. "auth_user" is (still) referenced in a ForeignKey constraint in your database structure. Such a thing shouldn't exist with your custom model, which is called "MyUser". In this case, the reference should be something like "accounts_myuser" or "myappname_myuser".

I guess, you've updated an already existing code including an old database. If you don't need the old admin logs, simply delete/drop the table called "django_admin_log" and then run "python manage.py syncdb" (or "python manage.py migrate" as of 1.7) to let Django re-create this table from scratch.

Be careful, though: If you have other tables referencing the "old" Django User model, you'll run again into the same kind of trouble in other locations.

like image 128
Simon Steinberger Avatar answered Nov 09 '22 21:11

Simon Steinberger


I ran into the same problem. Once you swap out the default Django user model for your own custom one, Django doesn't do anything to clean up old dependencies from the database that are no longer used. There's actually a few of the "auth_*" tables that have a foreign key constraint on the "auth_user" table.

Once you've switched over to your new auth models, make sure there's no data you need in any of the "auth_*" and "django_admin_log" tables, drop them, and re-run "manage.py syncdb". You'll notice it doesn't re-create the auth_user table as it's no longer used and the pesky constraint is gone.

like image 35
RaresMan Avatar answered Nov 09 '22 21:11

RaresMan