I'm trying to extent my user model. In the Django documentation for extending the user model it says:
... just want to add some additional profile information, you could simply subclass django.contrib.auth.models.AbstractUser
I don't have experience in subclassing models. I've set everything up except for subclassing the model to AbstractUser and can't seem to find good documentation on it. Does anyone have experience subclassing AbstractUser?
My models.py:
class AuthKey(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
authkey = models.CharField(max_length=100)
My admin.py:
class AuthKeyInline(admin.StackedInline):
model = AuthKey
can_delete = False
verbose_name_plural = 'AuthKey'
# Defines a new User admin
class UserAdmin(BaseUserAdmin):
inlines = (AuthKeyInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Related
So I was trying to add an imagefield in my model using the UserModel, so I made this models
from django.contrib.auth.models import User
from django.db import models
class ProfileImage(models.Model):
user = models.OneToOneField(User,
on_delete=models.CASCADE,
editable=False)
avatar = models.ImageField()
def user_avatar(self):
return self.profileimage.avatar
User.add_to_class('user_avatar', user_avatar)
And I made an admin to see the imagefield in the users,
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
# Register your models here.
UserAdmin.fieldsets += ('Custom fields set', {'fields': ('user_avatar',)}),
I dont kno what is wrong with my code, when I open a user to see the image field and , does anyone know what is the problem?
In admin fields and fieldsets expects you to list actual columns in the database. user_avatar is a function you've written so you can't list it as a field on the User model because it doesn't exist in that table.
Make a more generic model for all types of user information, not just an image, like this;
class Profile(models.Model):
"""
Profile model
"""
user = models.OneToOneField(
verbose_name=_('User'),
to=settings.AUTH_USER_MODEL,
related_name='profile',
on_delete=models.CASCADE
)
avatar = models.ImageField()
Then you can access the avatar with request.user.profile.avatar or in your admin register your Profile model as an inline to the User;
from django.contrib import admin
from django.contrib.auth import get_user_model
from myapp.accounts.models import Profile
User = get_user_model()
class ProfileInline(admin.StackedInline):
model = Profile
max_num = 1
can_delete = False
class MyUserAdmin(admin.UserAdmin):
inlines = [ProfileInline]
# unregister old user admin
admin.site.unregister(User)
# register new user admin that includes a UserProfile
admin.site.register(User, MyUserAdmin)
example field that i want to add in built in User model
class bulit_in_user_model(models.Model):
relationships = models.ManyToManyField('self',on_delete=models.CASCADE)
how to do that
Read more about referencing self using ManyToManyField.symmetrical here
from django.db import models
class MyUser(models.Model):
...
friends = models.ManyToManyField("self", blank=True)
Monkey patching could achieve your goal,but it's better to follow the normal User model Customization though
Inherit from AbstractUser, and specify AUTH_USER_MODEL = 'myapp.MyUser in your settings.
class MyUser(AbstractUser):
friends = models.ManyToManyField("self", blank=True)
I've been going back and forward between two tutorials on creating custom user models:
https://simpleisbetterthancomplex.com/tutorial/2018/01/18/how-to-implement-multiple-user-types-with-django.html
and https://wsvincent.com/django-tips-custom-user-model/
So far here is my code:
Model:
class CustomUser(AbstractUser):
is_admin = models.BooleanField('admin status', default=False)
is_areamanager = models.BooleanField('areamanager status', default=False)
is_sitemanager = models.BooleanField('sitemanager status', default=False)
Form:
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CustomUser
Admin:
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username',]
admin.site.register(CustomUser, CustomUserAdmin)
I have hit a bit of a wall at this point. I'm not sure what direction to go in with restricting content to users. My general idea is I want admins to access everything, area managers to have the next level of access, site manager after that, then regular users (false on all boolean checks) to have base privileges.
Is this the best route to go for this kind of implementation? Where should I go from here and why?
Don't extend the AbstractUser, user Django built-in groups and permissions to create class of users with different privileges:
https://docs.djangoproject.com/en/3.0/topics/auth/default/#groups
If you need to add more info to you user, a common pattern is to create a UserProfile:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
address = models.CharField(max_length=140)
age = ...
A couple of suggestions:
Use the AbstractUser just in case of specific use cases (for example when you need to customize the AuthenticationBackend)
Use the user ID and not the user profile id as FK in models (it is more easy to retrieve it from requests)
For basic use cases just adding a 'role' field to the UserProfile is enough for implementing a simple logic
I am trying to add some custom fields to a user, and extend the UserCreationForm so that I can add these fields when the user is created. I am following the docs but when I try to load the page to create a user I get an error: Unknown field(s) (username) specified for Customer.
The docs that I am following: Custom User and Auth Forms
models.py
class User(AbstractUser):
is_restaurant = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
class Customer(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
address = models.CharField(max_length=200)
def __str__(self):
return self.user.get_full_name()
forms.py
class CustomerSignUpForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = Customer
fields = UserCreationForm.Meta.fields + ('address',)
I understand that username is not part of the Customer class, but the docs appear to be doing the same thing...
The doc says:
If your custom user model is a simple subclass of AbstractUser, then
you can extend these forms in this manner...
In other words this will work only in case you want to add to the form is_restaurant or is_customer fields:
class CustomerSignUpForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields + ('is_restaurant',)
But in your case Customer is not subclass of AbstractUser, since this method is not working for you. As a workaround you can try to work with two separate forms in the same time as suggested in this answer.
I have a search model which has a ForeignKey relation to User
class Searches(models.Model):
user = models.ForeignKey(User)
......
I have a UserProfile model which has a OnetoOne Relationship to User
class UserProfile(models.Model):
user = models.OneToOneField(User)
photo = models.ImageField(upload_to='profile_images', blank=True)
ispublic=models.NullBooleanField()
I have attached UserProfile in admin.py as follows:
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
class UserProfileAdmin(UserAdmin):
inlines=(UserProfileInline, )
list_filter = UserAdmin.list_filter + ('email',)
list_display=('username','email','first_name','last_name','isPublic')
admin.site.unregister(get_user_model())
admin.site.register(get_user_model(), UserProfileAdmin)
Now I do not see a separate UserProfile but is integrated into User, which is what I want.
I also want to have Search model to show up in User admin. But also seperately.
how can I register two (or more) Admins to User model?
Try just putting another Inline inside the UserProfileAdmin, that will then place the UserProfileInline and SearchesInline in the UserProfileAdmin, then put admin.site.register(Searches) in admin.py. Unless I misunderstand the question.