Era Era - 1 month ago 34
Python Question

User Profile not saving profiles and throwing exceptions

I'm still new to Django and I've been reading through all the previous posts on User Profile and have tried adopting the solutions found. In doing so, I have been unable to actually save profiles to the database through the shell. Instead I'm receiving 'IntegrityError'.

My Profile Model:

class Profile(User):
user = models.OneToOneField(User, on_delete=models.CASCADE)
chunks = models.ManyToManyField(Chunk)

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()


I have changed my settings to authorise the profile module by including the following in settings:

AUTH_PROFILE_MODULE = 'pomodoro.Profile'


My problems occur when trying to create profiles for users.
In the shell I have tried this but get an auth error:

from django.contrib.auth.models import User
from pomodoro.models import Profile
admin_profile = Profile()
admin = User.objects.get(pk=1)
admin_profile.user = admin
admin_profile.save()
Traceback (most recent call last):
File "C:\Python35\lib\site-packages\django\db\backends\utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "C:\Python35\lib\site-packages\django\db\backends\sqlite3\base.py", line 337, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: UNIQUE constraint failed: auth_user.username

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Python35\lib\site-packages\django\contrib\auth\base_user.py", line 80, in save
super(AbstractBaseUser, self).save(*args, **kwargs)
File "C:\Python35\lib\site-packages\django\db\models\base.py", line 796, in save
force_update=force_update, update_fields=update_fields)
File "C:\Python35\lib\site-packages\django\db\models\base.py", line 823, in save_base
self._save_parents(cls, using, update_fields)
File "C:\Python35\lib\site-packages\django\db\models\base.py", line 848, in _save_parents
self._save_table(cls=parent, using=using, update_fields=update_fields)
File "C:\Python35\lib\site-packages\django\db\models\base.py", line 889, in _save_table
forced_update)
File "C:\Python35\lib\site-packages\django\db\models\base.py", line 939, in _do_update
return filtered._update(values) > 0
File "C:\Python35\lib\site-packages\django\db\models\query.py", line 654, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "C:\Python35\lib\site-packages\django\db\models\sql\compiler.py", line 1148, in execute_sql
cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
File "C:\Python35\lib\site-packages\django\db\models\sql\compiler.py", line 835, in execute_sql
cursor.execute(sql, params)
File "C:\Python35\lib\site-packages\django\db\backends\utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "C:\Python35\lib\site-packages\django\db\backends\utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "C:\Python35\lib\site-packages\django\db\utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "C:\Python35\lib\site-packages\django\utils\six.py", line 685, in reraise
raise value.with_traceback(tb)
File "C:\Python35\lib\site-packages\django\db\backends\utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "C:\Python35\lib\site-packages\django\db\backends\sqlite3\base.py", line 337, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: auth_user.username

Answer

Seconding what itzmeontv said about the inheritance AND one-to-one being redundant. As the documentation references, you can extend user model functionality by either using a one-to-one relationship, or by making a model that inherits from the built-in user model. One of the issues here is that you're doing both of those things, which is unnecessary and may lead to confusion down the road. https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#extending-the-existing-user-model

Regarding your specific error, the issue is coming about because you're trying to create a user object that has a username which already exists. The "user" that you're trying to create is actually the "admin_profile" object which has a non-unique username.

I'd imagine that this particular issue would resolve itself by having class Profile inherit from models.Model rather than from User.

from django.db import models

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    chunks = models.ManyToManyField(Chunk)

    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            Profile.objects.create(user=instance)

    @receiver(post_save, sender=User)
    def save_user_profile(sender, instance, **kwargs):
        instance.profile.save()