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.
Related
I have two one-to-one related models in Django. Simplified version as follows:
class User(models.Model):
name = models.CharField(max_length=40)
class Profile(models.Model):
age = models.IntegerField()
user = models.OneToOneField(User, on_delete=models.CASCADE)
I have used signals to automatically create a profile automatically when a new user is created.
I have also created a ProfileInline and included it in my UserAdmin as follows:
class ProfileInline(admin.TabularInline):
model = Profile
can_delete = False
class UserAdmin(admin.ModelAdmin):
list_display = ('name',)
inlines = [ProfileInline,]
The problem I am facing is that when a new User is being created in the admin module, and the person creating the new user also populates the field for the inline on the same page, an error is generated while saving because both the signals module and the admin are trying to create a new Profile.
Is there any way to prevent the ProfileInline from showing in the UserAdmin when adding a new User?
Thanks.
Add extra=0 in your ProfileInline to prevent create new profile instance when you create new User at admin side...
class ProfileInline(admin.TabularInline):
model = Profile
can_delete = False
extra = 0
class UserAdmin(admin.ModelAdmin):
list_display = ('name',)
inlines = [ProfileInline,]
OR You can use ModelAdmin get_inline_instances function. Following code removes inlines from add_view:
class ProfileInline(admin.TabularInline):
model = Profile
can_delete = False
class UserAdmin(admin.ModelAdmin):
list_display = ('name',)
inlines = [ProfileInline,]
def get_inline_instances(self, request, obj=None):
return obj and super(UserAdmin, self).get_inline_instances(request, obj) or []
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'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)
I have a problem with the CustomUser Model. Here is the model:
class CustomUser(models.Model):
department = models.ManyToManyField(Department)
game = models.ManyToManyField(Game)
user = models.OneToOneField(User)
In my user registration form, I want to have fields of User plus the Game and Department fields. Here's my form as of now:
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(max_length = '200')
last_name = forms.CharField(max_length = '200')
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'email')
I used User as my Model, so clearly it does not have the Game and Department fields as of now. At the same time, if I use CustomUser as a model in my form, I do have all the fields I need, but when I click the register button, an error: "CustomUser does not have a set_password attribute" appears.
Also, in Setting I have this:
CUSTOM_USER_MODEL = 'logins.CustomUser'
So how can I make the CustomUser Model have the attributes of User and have those fields appear in my form?
Thanks in advance!
When creating your own custom user model, it's usually best to subclass the AbstractBaseUser which includes those default fields and will generally make the process easier on you. OneToOne relationship to the default User model is more about expnding the built-in User model, which doesn't sound like what you're looking for. Read more about it here
As Daniel mentioned in the comments, this means you're going to have to explicitly include the username field (and you obviously have the freedom to define it as you'd like, it just has to be unique). In the example below I set up email to be the username
from django.contrib.auth.models import AbstractBaseUser
class CustomUser(AbstractBaseUser):
department = models.ManyToManyField(Department)
game = models.ManyToManyField(Game)
# user = models.OneToOneField(User)
email = models.EmailField(max_length=255, unique=True, db_index=True)
USERNAME_FIELD = 'email'
Now you need to include the password field in your form, and please look at the example given in the documentation, they do a better job explaining than I do.