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)
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 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)
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)
I'm new to Django and for a small project I need to open changelist of some models without any data. How we can prevent initial populating of some models?
You have to create your own ChangeList subclass. For example the following code will open an empty changelist but if you will search for name then the list will be populated by the search results:
from django.contrib.admin.views.main import ChangeList
class MyChangeList(ChangeList):
def get_queryset(self, request):
queryset = super(MyChangeList, self).get_queryset(request)
if not request.GET.get('q', ''):
queryset = queryset.none()
return queryset
class MyAdmin(admin.ModelAdmin):
search_fields = ['name']
def get_changelist1(self, request, **kwargs):
return MyChangeList
I'm making an election information app, and I want to allow the currently logged-in user to be able to declare himself and only himself as a candidate in an election.
I'm using Django's built-in ModelForm and CreateView. My problem is that the Run for Office form (in other words, the 'create candidate' form) allows the user to select any user in the database to make a candidate.
I want the user field in the Run for Office to be automatically set to the currently logged-in user, and for this value to be hidden, so the logged-in user cannot change the value of the field to someone else.
views.py
class CandidateCreateView(CreateView):
model = Candidate
form_class = CandidateForm
template_name = 'candidate_create.html'
def form_valid(self, form):
f = form.save(commit=False)
f.save()
return super(CandidateCreateView, self).form_valid(form)
forms.py
class CandidateForm(forms.ModelForm):
class Meta:
model = Candidate
models.py
class Candidate(models.Model):
user = models.ForeignKey(UserProfile)
office = models.ForeignKey(Office)
election = models.ForeignKey(Election)
description = models.TextField()
def __unicode__(self):
return unicode(self.user)
def get_absolute_url(self):
return reverse('candidate_detail', kwargs={'pk': str(self.id)})
Remove user field from rendered form (using exclude or fields, https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#selecting-the-fields-to-use )
class CandidateForm(forms.ModelForm):
class Meta:
model = Candidate
exclude = ["user"]
Find user profile and set user field in the create view.
class CandidateCreateView(CreateView):
...
def form_valid(self, form):
candidate = form.save(commit=False)
candidate.user = UserProfile.objects.get(user=self.request.user) # use your own profile here
candidate.save()
return HttpResponseRedirect(self.get_success_url())
Assumptions
We don't want to set null=True becaues we don't want to allow null users at the model and/or database level
We don't want to set blank=True to mess with the readability of model because the user actually will not be blank
#nbm.ten solution is a good one. It has an advantages over other 'solutions'to this problem that utilized model to set the user (like this one) in nbm.ten's doesn't undermine the assumptions above. We don't want to mess with the model to fix a problem in view!
But here I add two other solutions based on django documentation (Models and request.user):
Two other solutions
1. Using the generic CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import Candidate
class CandidateCreate(LoginRequiredMixin, CreateView):
model = Candidate
exclude = ['user']
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
2. Using class-based views
class CandidateForm(ModelForm):
class Meta:
model = Candidate
exclude = [ 'user',]
class CandidateAddView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
form = CandidateForm()
context = {'form':form}
return render(request, 'myapp/addcandidateview.html', context)
def post(self, request, *args, **kwargs):
form = CandidateForm(request.POST)
form.instance.user = request.user
if form.is_valid():
form.save()
return redirect(reverse('myapp:index'))
NOTES
Note that LoginRequiredMixin prevents users who aren’t logged in from accessing the form. If we omit that, we'll need to handle unauthorized users in form_valid() or post().
Also exclude = ['user'] prevents the user field to be shown on the form.
We used form.instance.user to set the user not form.data or form.cleaned_data they don't work