I have a question regarding permissions. I would like to separate my Users who are marked as Staff ( and can enter the administration page) through countries. So for example an admin from Netherlands can only see and edit the users from netherlands. What is the best approach to do that? Should I make the querys in a way so users can only see users from their own country and than I can customize it with permissions?
my models.py defines a country
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile', unique=True)
country = models.CharField("Country", max_length=150, blank=False)
and I thought about something like this in admin.py
def queryset(self, request):
qs = super(ProfileAdmin, self).queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(country=request.user.country)
You are thinking in the right direction. It is the proper way to filter objects visible to admins.
Small corrections: the name of the method is get_queryset() and to access the user's country you should use the profile relation:
def get_queryset(self, request):
qs = super(ProfileAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(country=request.user.profile.country)
UPDATE: To filter users in the standard User admin you have to replace the UserAdmin with your own subclass:
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class MyUserAdmin(UserAdmin):
def get_queryset(self, request):
qs = super(MyUserAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(profile__country=request.user.profile.country)
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
Related
i want give access to users to admin panel
i have a table :
class Todo(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
title = models.CharField(max_length=100)
date = models.DateTimeField()
def __str__(self):
return self.title
i want just allow users to see,edit,add and delete their own objects in admin panel not others.
i wrote this:
class TodoAdmin(admin.ModelAdmin):
def queryset(self, request):
queryset = super(TodoAdmin, self).queryset(request)
queryset = queryset.filter(user = request.user)
return queryset
but didnt work.
how can i do that?
You have to override get_queryset method as documented
The get_queryset method on a ModelAdmin returns a QuerySet of all
model instances that can be edited by the admin site. One use case for
overriding this method is to show objects owned by the logged-in user:
class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
I have the following model defined:
class PRegistration(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
create_date = models.DateTimeField(auto_now=False, auto_now_add=True)
teamName = models.CharField(max_length=144)
city = models.CharField(max_length=144)
How do I make all these fields read only in the admin page for all staff accounts except the superuser? I wanna do this without specifying the fields one by one so that I can reuse the code in multiple places.
Add the following function in the ModelAdmin subclass that you make in admin.py . The get_read_only function returns a list or a tuple which tells the fields that are to be made readonly. In the following code, the non-superuser staff accounts will see all fields as readonly, while the superuser will be able to edit all of those fields.
def get_readonly_fields(self, request, obj=None):
if request.user.is_staff:
if request.user.is_superuser:
return []
else:
return [f.name for f in self.model._meta.fields]
Special thanks: this question and its answers
If Your model.py contains
class PRegistration(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
create_date = models.DateTimeField(auto_now=False, auto_now_add=True)
teamName = models.CharField(max_length=144)
city = models.CharField(max_length=144)
If you want to make field user, teamName readonly for other staffs except superuser.
Add this code on your admin.py of same app.
#admin.register(PRegistration)
class PRegistrationAdmin(admin.ModelAdmin):
list_display = ['user']
search_fields = ['user']
readonly_fields = ['user', 'teamName']
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
return []
return self.readonly_fields
You can override the get_readonly_fields() method of AdminModel class:
from django.contrib import admin
from core import models
class UserAdmin(admin.ModelAdmin):
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
return [] # list of read only fields name
else:
return ['your fields names'] # list of read only fields name
admin.site.register(models.User, UserAdmin)
I have a simple model, say Resources. And I have fewer than 20 users and model admin serves the purpose to record requests.
Problem is that all users can see all records in model admin site.
Can this behaviour be changed to only show records created by same user only ?
Thank you in anticipation.
The django doc has an example that does almost exactly what you want:
https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset
The idea is to override the get_queryset() method in the model admin view:
# admin.py
from django.contrib import admin
class YourModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(MyModelAdmin, self).get_queryset(request)
return qs.filter(author=request.user)
admin.site.register(YourModel, YourModelAdmin)
You can adapt the queryset filter to even more specific needs at will.
UPDATE 2020:
Anyone who is curious as to what is the author field, then that is established in the models.py file of your app. For the admin.py part, you can visit the docs.
Step 1:
Make sure in your permissions you give access to the apps you want your users to have CRUD functionality over.
Step 2:
Admin.py
class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
Models.py
from django.contrib.auth import get_user_model
class Lecture(models.Model):
author = models.ForeignKey(get_user_model(), null=True, on_delete=models.CASCADE)
I am using the django admin site for my web app, but i am having a problem. I need that the staff users can change, create and delete another staff users, but i don't want that they change the informations of the superusers. I want to know if is possible filter the user list by role (the staff user don't see the superusers in the list).
Finally I found how to do this, I leave the code here just in case someone hav the same problem that I had
def get_queryset(self, request):
queryset = super(UserAdmin, self).get_queryset(request)
if request.user.is_superuser:
return queryset
return queryset.filter(is_superuser=False)
You will need to create a custom ModelAdmin for the User model. I recommend you to inherit from the original one and then you can override the get_queryset method.
You should end with:
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class MyUserAdmin(UserAdmin):
def get_queryset(self, request):
qs = super(MyUserAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
else:
return qs.filter(is_superuser=False)
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
In Django, I have created another separate Admin site. This is what my SiteUserAdmin class looks like:
class SiteUserAdmin(UserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('username' ,'email',)
fieldsets = (
(None,{'fields':('username','email','password')}),('Permissions',{'fields':('is_active','is_admin_user','groups')})
)
Among all the users, there are superusers whose "is_superuser = True". Is there anyway to hide such superusers from the list of editable users of the admin site?
In another word, I am not excluding other fields from the Admin site, but rather hide some instances of User from being edited in the Admin site.
How about just overriding the get_queryset() method.
class SiteUserAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(SiteUserAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(is_superuser=False)
Docs: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset
Override the get_queryset() method:
class SiteUserAdmin(UserAdmin):
...
def get_queryset(self, request):
qs = super(SiteUserAdmin, self).get_queryset(request)
return qs.exclude(is_superuser=True)