List of contacts per User when extending AbstractUser - django

I want to create a custom user model with some extra fields, among which a contact list of other users. I would like to extend AbstractUser instead of creating a new model with a one-to-one link to User.
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
a_custom_field = models.IntegerField(default=0)
# per-user contact list
contacts = models.ManyToManyField(get_user_model())
This code doesn't work. Throwing this error during makemigrations.
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'users.CustomUser' that has not been installed
The error totally makes sense, but what's the right way to achieve this?

I found the solution just by digging more into the django docs.
The problem is that I cannot use get_user_model() before the user model has been created.
The solution is using the class name as a string. So, this code works great:
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
a_custom_field = models.IntegerField(default=0)
# per-user contact list
contacts = models.ManyToManyField('CustomUser')

Related

Django - Is there a difference between auth.models.User and .model.User (abstract)?

I have to import the User model in a file and I was wondering if there is any difference between the auth.models.User and an abstract user in .models.User:
from django.contrib.auth.models import User
or
from .models import User
The first one from django.contrib.auth.models import User is the standard extension of AbstractUser with no additional fields. Whereas your from .models import User is your customised User model that should also inherit from AbstractUser but has customisation for your Django project.
You can see what django.contrib.auth.models does in the source code on GitHub.

Django - using intermediate user group model

I need to use the intermediate model between user and group in another model like this:
Class SomeModel(models.Model):
usergroup = models.ForeignKey(UserGroupIntermediate, on_delete=models.DO_NOTHINH)
That is possible?
Thanks!
EDIT!:
My model looks like this, i'm using a custom user model:
from django.db import models
from django.contrib.auth import get_user_model
from model_utils.models import TimeStampedModel
class Enrollment(TimeStampedModel):
usergroups = models.ForeignKey(
get_user_model().groups.through,
but, this return an error when execute makemigrations
enrollments.Enrollment.usergroups: (fields.E300) Field defines a relation with model 'User_groups', which is either not installed, or is abstract.
You can refer to the model via the through attribute of the field.
usergroup = models.ForeignKey(User.groups.through, ...)

Django Custom User Model Best Practice: User = get_user_model()?

I'm trying to create a custom user class and I'd like to know the best practice for implementing referencing the new user. After following the Django docs method of implementing the custom user as follows in models.py:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
And settings.py
AUTH_USER_MODEL = 'myapp.MyUser'
And admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)
The Django docs say to use settings.AUTH_USER_MODEL in place of user specifically for ForeignKeys and OnetoOneField, but it's not clear about other instances.
My question is specific to how to refer to the custom user class in views.py. Before defining the user class I was using
from django.contrib.auth.models import User
But after defining a custom class this is no longer correct. I've seen boilerplate code use this method in the beginning of views.py:
from django.contrib.auth import get_user_model
User = get_user_model()
Is this the best practice for referencing the custom user? Or should I just be using settings.AUTH_USER_MODEL in place of where I previously had User?
Using settings.AUTH_USER_MODEL will load the user class lazily after all django apps are loaded. Calling get_user_model() on a module level when your app is initially loaded may result in that the user model app is not loaded and also circular imports.
Update: I read two specific questions:
How to correctly access the user model, contrib or custom.
Djangos get_user_model() is quite simply a call to django.apps get_model() using the settings.AUTH_USER_MODEL. If you are writing apps that might be reused in other projects with other user models, use the get_user_model call. Always. Then it doesn't matter what the user model is.
If you have created your own core.User model and is very confident that your code will only be used in this project, from core.models import User works as well.
When to use the string representation from settings instead of fetching the model.
The string representation will in the end usually call the same django.apps get_model() anyway. By giving a string instead of the class itself in Foreignkeys, OneToOneFields etc you simply don't require the model to be looked up during django app imports, where the user model may not yet be available. So using string representation is simply deferred loading of a model. The same goes for all models.
An also during djangos different major versions this behavior have changed, which is another topic. Notice that get_user_model() have been updated in Django 1.11 for import usage.
https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#referencing-the-user-model
you can go with get_user_model instead User
from django.contrib.auth import get_user_model
User = get_user_model()
get_user_model will Returns the User model that is active in this project.
if you modify(adding new field into it) default User table you need to use get_user_model it will return active User table.
BTW User will return native from django.contrib.auth.models

Django, how to ForeignKey(auth_user)?

I am a newbie of django. I want to make a ForeignKey to the auth_user table.
I try to do that:
user = models.ForeignKey(auth_user)
It cause the error:
NameError: name 'auth_user' is not defined
So, can somebody tell me how to import auth_user.
Since foreign keys accept strings, you can use the AUTH_USER_MODEL setting in your foreign key.
from django.conf import settings
class MyModel(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
This works whether you are using the built in User model, or a custom model.
Presumably you are talking about django.contrib.auth.models.User then do
from django.contrib.auth.models import User
class MyModel(models.model):
user = models.ForeignKey(User)
If you are talking about a custom User model that comes from elsewhere, replace the import with the relevent import for that class.

Django AbstractUser not working properly

I am trying to inherit from AbstractUSer my models.py looks like:
class MyUser(AbstractUser):
created = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username',]
MyUser._meta.get_field_by_name('email')[0]._unique=True
now by declaring email as unique field and username as a required field my superuser is being created successfully and also is being authenticated properly but I am having a problem while creating any other user as if I am creating any user through my admin page its not being authenticated.It always returns
None
My admin.py:
from django.contrib import admin
from credilet.models import *
admin.site.register(MyUser)
What I am thinking is that the create_user is not being called properly as if I see in my admin page the password is not hashed so that means the create_user is not being called properly.Somebody please help through it or even if you have a proper documentation on abstractuser
not abstractbaseuser
so please refer that to me in the solutions.
Thanks
If you want to change the authentication system you have to use AbstractBaseUser,
look at this full example.
AbstractUser is ok to Extend Django’s default User.
I think you should add UserAdmin into admin.py for Myuser
if you does not add UserAdmin , password can't be hashed with django:
from django.contrib import admin
from credilet.models import *
from django.contrib.auth.admin import UserAdmin
admin.site.register(MyUser, UserAdmin) # add UserAdmin