Export User model into different app - python

I have a project with one app, where user, their posts and other models are located. Now I want to separate User model and put it into different app, called users.
How should I do this correctly? And how do I use this model in the old app?
User model of the first app looks like this:
class User(AbstractUser):
class Meta:
permissions = (
('can_do_this', 'Permission1'),
('can_do_that', 'Permission2'),
...,
)
User model of the second (users)app looks like this:
class ExternalUser(AbstractUser):
class Meta:
permissions = (
('can_do_this', 'Permission1'),
('can_do_that', 'Permission2'),
...,
)
I've done django-admin startapp users and copy-pasted user's model code into created app models.py.
Then I tried makemigrations and it failed, showing:
SystemCheckError: System check identified some issues:
ERRORS:
photogal.User.groups: (fields.E304) Reverse accessor for 'User.groups'
clashes with reverse accessor for 'ExternalUser.groups'.
HINT: Add or change a related_name argument to the definition for
'User.groups' or 'ExternalUser.groups'.
photogal.User.user_permissions: (fields.E304) Reverse accessor for
'User.user_permissions' clashes with reverse accessor for
'ExternalUser.user_permissions'.
HINT: Add or change a related_name argument to the definition for
'User.user_permissions' or 'ExternalUser.user_permissions'.
users.ExternalUser.groups: (fields.E304) Reverse accessor for
'ExternalUser.groups' clashes with reverse accessor for 'User.groups'.
HINT: Add or change a related_name argument to the definition for
'ExternalUser.groups' or 'User.groups'.
users.ExternalUser.user_permissions: (fields.E304) Reverse accessor for
'ExternalUser.user_permissions' clashes with reverse accessor for
'User.user_permissions'.
HINT: Add or change a related_name argument to the definition for
'ExternalUser.user_permissions' or 'User.user_permissions'.
Adding related_name='+' to the old user model resulted in:
ERRORS:
<class 'django.contrib.auth.admin.UserAdmin'>: (admin.E020) The value of
'filter_horizontal[0]' must be a many-to-many field.
<class 'django.contrib.auth.admin.UserAdmin'>: (admin.E020) The value of
'filter_horizontal[1]' must be a many-to-many field.
Thanks!

Simply delete the old User model from the previous app, and put the new one in the new app, so that in the end you only have one User class that extends the AbstractUser class.
As for your second issue, try this.
I hope this helps.

Related

How can a model have multiple keys with the same type of models as values?

I'm making an application and I should make a Model which have 2 keys that saves models of the same type.
It's not easy to express in English so I will upload the image of the situation.
In Food Pair Model ( or we can call it table I think )
I want to refer Food Model But I wasn't able to use ForeignKey or ManyToManyField.
ERRORS:
food_test.FoodQuestion.left_food: (fields.E304) Reverse accessor for 'FoodQuestion.left_food' clashes with reverse accessor for 'FoodQuestion.right_food'.
HINT: Add or change a related_name argument to the definition for 'FoodQuestion.left_food' or 'FoodQuestion.right_food'.
food_test.FoodQuestion.right_food: (fields.E304) Reverse accessor for 'FoodQuestion.right_food' clashes with reverse accessor for 'FoodQuestion.left_food'.
HINT: Add or change a related_name argument to the definition for 'FoodQuestion.right_food' or 'FoodQuestion.left_food'.
I don't know what database relation to use in this case and how to make it.
What can I use for this case?
When you create a ForeignKey from one model to another Django will dynamically create a property on the model being referenced that will return a QuerySet with all objects that have the foreign key to that object
For example
class Foo(models.Model):
pass
class Bar(models.Model):
foo = models.ForeignKey(Foo, on_delete=models.CASCADE)
foo = Foo.objects.create()
bar = Bar.objects.create(foo=foo)
foo.bar_set.all() # This will return a queryset containing foo
By default this property will be <model_name_lowercase>_set. In your case because you have 2 foreign keys from one model to the same model Django is trying to create the same property on the Food model for each foreign key.
To get around this issue you can specify the name of this property using related_name, if you set this to '+' no reverse relation will be made at all or give them unique names
class FoodQuestion(models.Model):
left_food = models.ForeignKey(Food, on_delete=models.CASCADE, related_name='+')
left_food = models.ForeignKey(Food, on_delete=models.CASCADE, related_name='+')
You must define a unique related_name for each ForeignKey field in your FoodPair model.
class FoodPair(models.Model):
first_food = models.ForeignKey(Food, related_name="first_food")
second_food = models.ForeignKey(Food, related_name="second_food")
what_i_buy = models.ForeignKey(Food, related_name="what_i_buy")
If related_name is not defined Django automatically sets it and when there is multiple ForeignKey fields pointing to the same model the names clash.

Reverse accessor clashes in Django when adding custom user. Adding AUTH_USER_MODEL in settings.py doesn't work either

I got reverse accessor clashes error when trying to use a custom user model. I added AUTH_USER_MODEL in settings.py but still get the same error.
I am writing a Django project (Django version 2.2.2) when at a point I want to change to use the custom user model. There are already a couple of models, but it's fine to clear the database to start over at this stage, so I have deleted the sqlite3.db and all the migrations.
So to have a custom user model as per django documentation, I added:
in models.py:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
... # other models
in settings.py:
AUTH_USER_MODEL = 'polls.User'
After that,
python .\manage.py makemigrations
should just work.
But it doesn't. It showed the same message as if I didn't add AUTH_USER_MODEL in settings.py at all:
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'User.groups'.
HINT: Add or change a related_name argument to the definition for 'User.groups' or 'User.groups'.
auth.User.user_permissions: (fields.E304) Reverse accessor for 'User.user_permissions' clashes with reverse accessor for 'User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'User.user_permissions' or 'User.user_permissions'.
polls.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'User.groups'.
HINT: Add or change a related_name argument to the definition for 'User.groups' or 'User.groups'.
polls.User.user_permissions: (fields.E304) Reverse accessor for 'User.user_permissions' clashes with reverse accessor for 'User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'User.user_permissions' or 'User.user_permissions'.
No idea what could go wrong. Looks like most people around getting the same error is that they missed AUTH_USER_MODEL.
PS:
"polls" is my app name.
Tried change the custom user model's class name to something else for example "NovelUser" (replace the class name in models.py and AUTH_USER_MODEL in settings.py), still get the same type of error:
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'NovelUser.groups'.
etc.
PS: Don't think I have redefined any groups. I created a group in admin before I purged the database for this, but I have deleted splite3.db so I think that shouldn't matter.
PS: Defining AUTH_USER_MODEL simply seems to have no effect - if I comment out
class User(AbstractUser):
pass
Then no errors would be found while the default user model would be used.
OK, I was editing the wrong settings.py (I have a copy of settings.py under the 1st "mysite" which I couldn't recall how and why I added them in the first place. I know when thanks to git, but still totally puzzled at how and why I have done that at all even looking at that changelist).
The directory is like:
mysite
|- mysite
| |- settings.py <- Should modify this one
| |- ......
| polls
| |- (where most contents should be, including models.py etc)
| |- ......
|- db.sqlite3
|- settings.py <- I had a copy of this file here and was modifying this file! Of course it won't work
OK, surely it's such a dumb mistake/question at the 1st place. However, based on the information I have given it is impossible for anyone than me to find out what's wrong, and also very difficult for me...

Error using permission on custom User model

I am making a custom user model using AbstractUser in django.contrib.auth.models.
Everything was working fine until I wanted to make some changes in user_permissions of my SiteUser then Django gave an error that SiteUser has no attribute named user_permissions
Then I thought of extending PermissionMixin in django.contrib.auth.models to my SiteUser class to make changes in user_permissions but now It is throwing this error:
project.SiteUser.user_permissions: (fields.E304) Reverse accessor for 'SiteUser.user_permissions' clashes with reverse accessor for 'SiteUser.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'SiteUser.user_permissions' or 'SiteUser.user_permissions'.
project.SiteUser.user_permissions: (fields.E304) Reverse accessor for 'SiteUser.user_permissions' clashes with reverse accessor for 'SiteUser.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'SiteUser.user_permissions' or 'SiteUser.user_permissions'.
project.SiteUser.user_permissions: (fields.E331) Field specifies a many-to-many relation through model 'project.SiteUser_user_permissions', which has not been installed.
P.S. - I have used AUTH_USER_MODEL='project.CustomUser'

django-oscar integration error

I integration ecommerce into my code. And run into problem with Product. When i update me models.py with simple
class MyProduct(AbstractProduct):
pass
or even extend my Package model with AbstractProduct and try to create migrations the next error appears.
catalogue.Product.product_class: (fields.E304) Reverse accessor for 'Product.product_class' clashes with reverse accessor for 'Package.product_class'.
HINT: Add or change a related_name argument to the definition for 'Product.product_class' or 'Package.product_class'.
catalogue.Product.product_class: (fields.E305) Reverse query name for 'Product.product_class' clashes with reverse query name for 'Package.product_class'.
HINT: Add or change a related_name argument to the definition for 'Product.product_class' or 'Package.product_class'.
catalogue.ProductAttributeValue: (fields.E336) The model is used as an intermediate model by 'ckanwrap.Package.attributes', but it does not have a foreign key to 'Package' or 'ProductAttribute'.
catalogue.ProductCategory: (fields.E336) The model is used as an intermediate model by 'ckanwrap.Package.categories', but it does not have a foreign key to 'Package' or 'Category'.
catalogue.ProductRecommendation: (fields.E336) The model is used as an intermediate model by 'ckanwrap.Package.recommended_products', but it does not have a foreign key to 'Package' or 'Product'.
ckanwrap.Package.product_class: (fields.E304) Reverse accessor for 'Package.product_class' clashes with reverse accessor for 'Product.product_class'.
HINT: Add or change a related_name argument to the definition for 'Package.product_class' or 'Product.product_class'.
ckanwrap.Package.product_class: (fields.E305) Reverse query name for 'Package.product_class' clashes with reverse query name for 'Product.product_class'.
HINT: Add or change a related_name argument to the definition for 'Package.product_class' or 'Product.product_class'.
ckanwrap.Package.recommended_products: (fields.E335) The model is used as an intermediate model by 'ckanwrap.Package.recommended_products', but it has more than one foreign key to 'Product', which is ambiguous. You must specify which foreign key Django should use via the through_fields keyword argument.
HINT: If you want to create a recursive relationship, use ForeignKey("self", symmetrical=False, through="ProductRecommendation").
Any suggestions?
If anyone is still getting this problem, the solution is to create a class with the same name used by oscar. In this case, it would be Product.
from oscar.apps.catalogue.abstract_models import AbstractProduct
from django.db import models
class Product(AbstractProduct):
additional_field = models.CharField(max_length=200)
from oscar.apps.catalogue.models import *

Django: related_name Reverse accessor

I have this model where InstitutePerson is a subclass of Person.
Person
InstitutePerson
Project
In Project:
participants_institite = models.ManyToManyField(InstitutePerson, blank = True, null = True)
participants_exterior = models.ManyToManyField(Person, blank = True, null = True)
I get an error:
Project.participants_institute: (fields.E304) Reverse accessor for 'Project.participants_institute' clashes with reverse accesor for 'Project.participants_exterior'.
I thought that related_name would solve the problem but after seeing some posts (related_name argument not working as expected in Django model?) I'm not sure how to proceed because of the inheritance among the classes.
Use related_name arg and define it manually
https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.related_name
If you have two M2M field with same type Django can't generate properties on target modela automatically.
if you are not intereset in reversed direction, you can simply ise
models.ManyToManyField(..., related_name='+r1')
models.ManyToManyField(..., related_name='+r2')

Categories

Resources