Q-bart
Q-bart

Reputation: 1591

ValueError: Lookup failed for model referenced by field

I have made Custom User model in my Django project. Here it is:

class CustomUser(User):
    avatar = models.ImageField(upload_to='avatars')
    about_myself = models.TextField(max_length=300)

    USERNAME_FIELD = 'username'

    def __str__(self):
        return self.username

    def is_author(self):
        return 'blog.change_post' and 'blog.add_post' in self.get_all_permissions()

And after it, I changed all Foreign Keys of user to new CustomUser model. It works OK. But I make one new migration and django cause error, when I want to migrate it:

ValueError: Lookup failed for model referenced by field blog.Comment.author: main.CustomUser

My blog.Comment model:

class Comment(models.Model):
    content = models.TextField()
    author = models.ForeignKey(CustomUser)
    date_create = models.DateTimeField(auto_now_add=True)
    post = models.ForeignKey(Post)

What should I do?

Thanks!

Upvotes: 2

Views: 360

Answers (1)

Peter Hinson
Peter Hinson

Reputation: 103

Judging from the code you posted, you might be might be better served by extending the user model rather than replacing it. This pattern is usually called a profile model and works via a one-to-one relationship with User.

Profiles provides application specific fields and behaviors, while allowing User to go about it's usual business unchanged. It doesn't require you to muck around with rewriting auth or even necessarily change your foreign keys.

Here's an example of your code written as a profile:

class Profile(models.Model):
    # Link to user :
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    avatar = models.ImageField(upload_to='avatars')
    about_myself = models.TextField(max_length=300)

    def __str__(self):
        return self.user.username

    def is_author(self):
        return 'blog.change_post' and 'blog.add_post' in self.user.get_all_permissions()

Comment model:

class Comment(models.Model):
    content = models.TextField()
    author = models.ForeignKey(settings.AUTH_USER_MODEL)
    date_create = models.DateTimeField(auto_now_add=True)
    post = models.ForeignKey(Post)

    # How to access the profile:
    def check_author(self):
        self.author.profile.is_author()

You'll also want to add a signal to create a new profile when a user is registered:

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile_for_new_user(sender, created, instance, **kwargs):
    if created:
        profile = Profile(user=instance)
        profile.save()

Django docs on extending users.

If a profile approach doesn't work for you, try inheriting from AbstractUser or AbstractBaseUser instead of User. The abstract models provide the same basic functionality as User and are the preferred technique for recent Django versions.

There are a handful of additional steps however, check out the docs on creating custom users for a run down.

Upvotes: 1

Related Questions