Inherit from abstract class Django - django

I am building a platform with 3 users roles: Admin, Creator and Brand. I redefined a default django User to be able to login by email.
class AbstractUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=32, unique=True)
first_name = models.CharField(max_length=32, blank=True)
last_name = models.CharField(max_length=64, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
location = models.CharField(max_length=120, blank=True)
bio = models.TextField(blank=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
class Meta:
abstract = True
def __str__(self):
return self.email
I made this class an abstract one to be able to add new classes, inherit from the Abstract class and redefine their attributes.
class PlatformAdmin(AbstractUser):
pass
class Creator(AbstractUser):
email = models.EmailField(max_length=32, unique=True, error_messages={
'unique': "A customer with that email already exists.",
})
class Brand(AbstractUser):
name = models.CharField(max_length=64)
I also add in settings.py following:
AUTH_USER_MODEL = 'users.PlatformAdmin'
Now when I run makemigrations it will give the following output:
users.Brand.groups: (fields.E304) Reverse accessor for 'Brand.groups' clashes with reverse accessor for 'Creator.groups'.
HINT: Add or change a related_name argument to the definition for 'Brand.groups' or 'Creator.groups'.
users.Brand.groups: (fields.E304) Reverse accessor for 'Brand.groups' clashes with reverse accessor for 'PlatformAdmin.groups'.
HINT: Add or change a related_name argument to the definition for 'Brand.groups' or 'PlatformAdmin.groups'.
users.Brand.user_permissions: (fields.E304) Reverse accessor for 'Brand.user_permissions' clashes with reverse accessor for 'Creator.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'Brand.user_permissions' or 'Creator.user_permissions'.
users.Brand.user_permissions: (fields.E304) Reverse accessor for 'Brand.user_permissions' clashes with reverse accessor for 'PlatformAdmin.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'Brand.user_permissions' or 'PlatformAdmin.user_permissions'.
users.Creator.groups: (fields.E304) Reverse accessor for 'Creator.groups' clashes with reverse accessor for 'Brand.groups'.
HINT: Add or change a related_name argument to the definition for 'Creator.groups' or 'Brand.groups'.
users.Creator.groups: (fields.E304) Reverse accessor for 'Creator.groups' clashes with reverse accessor for 'PlatformAdmin.groups'.
HINT: Add or change a related_name argument to the definition for 'Creator.groups' or 'PlatformAdmin.groups'.
users.Creator.user_permissions: (fields.E304) Reverse accessor for 'Creator.user_permissions' clashes with reverse accessor for 'Brand.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'Creator.user_permissions' or 'Brand.user_permissions'.
users.Creator.user_permissions: (fields.E304) Reverse accessor for 'Creator.user_permissions' clashes with reverse accessor for 'PlatformAdmin.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'Creator.user_permissions' or 'PlatformAdmin.user_permissions'.
users.PlatformAdmin.groups: (fields.E304) Reverse accessor for 'PlatformAdmin.groups' clashes with reverse accessor for 'Brand.groups'.
HINT: Add or change a related_name argument to the definition for 'PlatformAdmin.groups' or 'Brand.groups'.
users.PlatformAdmin.groups: (fields.E304) Reverse accessor for 'PlatformAdmin.groups' clashes with reverse accessor for 'Creator.groups'.
HINT: Add or change a related_name argument to the definition for 'PlatformAdmin.groups' or 'Creator.groups'.
users.PlatformAdmin.user_permissions: (fields.E304) Reverse accessor for 'PlatformAdmin.user_permissions' clashes with reverse accessor for 'Brand.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'PlatformAdmin.user_permissions' or 'Brand.user_permissions'.
users.PlatformAdmin.user_permissions: (fields.E304) Reverse accessor for 'PlatformAdmin.user_permissions' clashes with reverse accessor for 'Creator.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'PlatformAdmin.user_permissions' or 'Creator.user_permissions'.
I can't figure out what I am doing wrong and how to solve this issue.

I think you have to add 3 fields like this:
class AbstractUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=32, unique=True)
first_name = models.CharField(max_length=32, blank=True)
last_name = models.CharField(max_length=64, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
location = models.CharField(max_length=120, blank=True)
bio = models.TextField(blank=True)
# add this 3 fields
is_admin = models.BooleanField(default=False)
is_creater = models.BooleanField(default=False)
is_brand = models.BooleanField(default=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
class Meta:
abstract = True
def __str__(self):
return self.email
AUTH_USER_MODEL = 'users.CustomUserModel'
I think you have to follow this method.

inside AbstractUser in class Meta, abstract=True is creating the problem. also you are repeating the email field in 2 places (AbstractUser and Creator).
OR
keep only one user model(PlatformAdmin). convert Creator and Brand as normal model. otherwise fields from PermissionsMixin class are clashing(same fields are repeating in multiple places).

Related

in django two fields with foreign keys from one model to link two fields from another model

I have a "ModelVoiture" model with a foreign key "type_carburant" field and I can access the "typeCarburant" field of the "Carburant" model. I need to access another field of the same model "Carburant", the field "prixCarburant" from the model "ModelVoiture" but if I add the line
prixCarburant = models.ForeignKey(Carburant, on_delete=models.CASCADE)
i have this error
coutcarbur.ModelVoiture.prixCarburant: (fields.E304) Reverse accessor 'Carburant.modelvoiture_set' for 'coutcarbur.ModelVoiture.prixCarburant' clashes with reverse accessor for 'coutcarbur.ModelVoiture.typeCarburant'.
HINT: Add or change a related_name argument to the definition for 'coutcarbur.ModelVoiture.prixCarburant' or 'coutcarbur.ModelVoiture.typeCarburant'.
coutcarbur.ModelVoiture.typeCarburant: (fields.E304) Reverse accessor 'Carburant.modelvoiture_set' for 'coutcarbur.ModelVoiture.typeCarburant' clashes with reverse accessor for 'coutcarbur.ModelVoiture.prixCarburant'.
HINT: Add or change a related_name argument to the definition for 'coutcarbur.ModelVoiture.typeCarburant' or 'coutcarbur.ModelVoiture.prixCarburant'.
my code in coutcarbur/models.py
class MarqueVoiture(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Carburant(models.Model):
name = models.CharField(max_length=50)
prixCarburant = models.DecimalField(max_digits=6, decimal_places=2)
typeCarburant = models.CharField(max_length=50)
def __str__(self):
return self.name
class ModelVoiture(models.Model):
name = models.CharField(max_length=50)
consolitre = models.DecimalField(
max_digits=6, decimal_places=2)
prixCarburant = models.ForeignKey(Carburant, on_delete=models.CASCADE)
typeCarburant = models.ForeignKey(Carburant, on_delete=models.CASCADE)
marque = models.ForeignKey(MarqueVoiture, on_delete=models.CASCADE)
def __str__(self):
return self.name
how to implement related_name function in template to solve this problem.
I must surely revise the diagram of my models?
thanks for any help.

How to save a User as an attribute of a model Django

I am trying to create a Mail function as part of my website, I would like to save the receiving User instead of the receiving User's username in the receiver part of the Mail class, so I don't have to filter the User. This is what I did:
class Mail(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE)
receiver = models.ForeignKey(User, on_delete=models.CASCADE, choices=[(u.username, u) for u in User.objects.all()])
title = models.CharField(max_length=50)
content = models.TextField()
django is giving me this error
ERRORS:
mail.Mail.sender: (fields.E304) Reverse accessor for 'mail.Mail.sender' clashes with reverse accessor for 'mail.Mail.receiver'.
HINT: Add or change a related_name argument to the definition for 'mail.Mail.sender' or 'mail.Mail.receiver'.
mail.Mail.receiver: (fields.E304) Reverse accessor for 'mail.Mail.receiver' clashes with reverse accessor for 'mail.Mail.sender'.
HINT: Add or change a related_name argument to the definition for 'mail.Mail.receiver' or 'mail.Mail.sender'.
You need to add related_name attribute. For more information read this post:
What is related_name used for?
class Mail(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sender')
receiver = models.ForeignKey(User, on_delete=models.CASCADE, choices=[(u.username, u) for u in User.objects.all()], related_name='receiver')
title = models.CharField(max_length=50)
content = models.TextField()

Django getting error: "Reverse accessor for" in Models

I am trying to create a db model using django inspect db and it is generating all the models but I am getting error.
I am using this command to generate db models for existing database:
python manage.py inspectdb > models.py
It is generating models accurately but in fileds such as this:
create_uid = models.ForeignKey('self', models.DO_NOTHING,db_column='create_uid', blank=True, null=True)
write_uid = models.ForeignKey('self',models.DO_NOTHING, db_column='write_uid', blank=True, null=True)
I am getting error:
polls.ResUsers.create_uid: (fields.E304) Reverse accessor for 'ResUsers.create_uid' clashes with reverse accessor for 'ResUsers.write_uid'.
HINT: Add or change a related_name argument to the definition for 'ResUsers.create_uid' or 'ResUsers.write_uid'.
polls.ResUsers.write_uid: (fields.E304) Reverse accessor for 'ResUsers.write_uid' clashes with reverse accessor for 'ResUsers.create_uid'.
HINT: Add or change a related_name argument to the definition for 'ResUsers.write_uid' or 'ResUsers.create_uid'.
I am adding related names like this:
create_uid = models.ForeignKey('self', models.DO_NOTHING,related_name='create_uid',db_column='create_uid', blank=True, null=True)
What should I do in order to use generated models. I am using postgres.
I am updating my question one of the answer worked for me when I am using it like this:
create_uid = models.ForeignKey(
'self',
models.DO_NOTHING,
db_column='create_uid',
related_name='created_items',
blank=True,
null=True
)
In one other model class when I am using this code like this:
create_uid = models.ForeignKey(
'ResUsers',
models.DO_NOTHING,
db_column='create_uid',
related_name='created_items',
blank=True,
null=True
)
I am getting the error:
polls.ResUsers.create_uid: (fields.E304) Reverse accessor for 'ResUsers.create_uid' clashes with reverse accessor for 'SurveyUserInput.create_uid'.
HINT: Add or change a related_name argument to the definition for 'ResUsers.create_uid' or 'SurveyUserInput.create_uid'.
The related_name=… [Django-doc] is the name of the relation in reverse. So it is meant to access all model objects with as create_uid/write_uid the object. This can result in a QuerySet of zero, one or more elements.
Therefore the related_names of two ForeignKeys to the same model, can not be the same, since that would make the model ambiguous. Since your ForeignKeys refer to the 'self' model, you can not even given these the name of a field that already exists.
You thus might want to give the relations a name like:
class MyModel(models.Model):
create_uid = models.ForeignKey(
'self',
models.DO_NOTHING,
db_column='create_uid',
related_name='created_items',
blank=True,
null=True
)
write_uid = models.ForeignKey(
'self',
models.DO_NOTHING,
db_column='write_uid',
related_name='written_items',
blank=True,
null=True
)

Django ManyToManyField SystemCheckError

class Professional(models.Model):
...
favoriting_customers = models.ManyToManyField(
'customers.Customer', blank=True,
through='favorites.FavoriteProfessional')
recommending_customers = models.ManyToManyField(
'customers.Customer', blank=True,
through='recommendations.ProfessionalRecommendation')
I get no errors when I delete on of the ManyToMany fields. However, I get SystemCheckError when I run 'python manage.py makemigrations'.
ERRORS:
professionals.Professional.favoriting_customers: (fields.E304) Reverse accessor for 'Professional.favoriting_customers' clashes with reverse accessor for 'Professional.recommending_customers'.
HINT: Add or change a related_name argument to the definition for 'Professional.favoriting_customers' or 'Professional.recommending_customers'.
professionals.Professional.recommending_customers: (fields.E304) Reverse accessor for 'Professional.recommending_customers' clashes with reverse accessor for 'Professional.favoriting_customers'.
HINT: Add or change a related_name argument to the definition for 'Professional.recommending_customers' or 'Professional.favoriting_customers'.
As suggested by the HINT, you need to use related_name to avoid clashes on backward relations. You are going to need this every time you have two fields in the same model with a relation to the same object (customers.Customer in your case).
You can try something like this:
class Professional(models.Model):
...
favoriting_customers = models.ManyToManyField(
'customers.Customer', blank=True,
through='favorites.FavoriteProfessional',
related_name='favorites'
)
recommending_customers = models.ManyToManyField(
'customers.Customer', blank=True,
through='recommendations.ProfessionalRecommendation',
related_name='recommendations'
)
If you are not interested in backward relation to Professional table, you can disable it by using '+' as the related_name:
class Professional(models.Model):
...
favoriting_customers = models.ManyToManyField(
'customers.Customer', blank=True,
through='favorites.FavoriteProfessional',
related_name='+'
)
recommending_customers = models.ManyToManyField(
'customers.Customer', blank=True,
through='recommendations.ProfessionalRecommendation',
related_name='+'
)
Also, you should be careful with related_name

Django m2m relation of the model with itself with extra attributes

I tried to create a model with a many to many self relation, i put this in my code:
class Person(models.Model):
name = models.CharField(max_length=50)
shape_clm = models.ManyToManyField("self", through='Friend', symmetrical=False)
def __str__(self):
return self.name
class Friend(models.Model):
pers_one = models.ForeignKey(Person)
pers_two = models.ForeignKey(Person)
type = models.CharField(max_length=150)
But when i tried to migrate the model to the DB the following error is raised:
Friend.pers_one: reverse accessor for Friend.pers_one clashes with reverse accessor for Friend.pers_two
I'm using Postgres as DB server, how i can make this m2m relation?
You need to add the related_name keyword argument, otherwise the ORM can't tell how will you refer to either of the fields.
class Friend(models.Model):
pers_one = models.ForeignKey(Person, related_name='pers_ones')
pers_two = models.ForeignKey(Person, related_name='pers_twos')
Add related_name arguments to your ForeignKeys in the Friend ModelClass:
class Friend(models.Model):
pers_one = models.ForeignKey(Person, related_name="friends_one")
pers_two = models.ForeignKey(Person, related_name="friends_two")
type = models.CharField(max_length=150)
For more information about related_name take a look at the docs.