I have a problem with achieving this functionality: An administrator must be able to view data for a specific user group in the administration page, how could I do this in my django project?
Thank you in advance for your answers
There are a few ways to do this.
Assuming a custom usermodel with a custom property called group_admin_name, this would restrict the ability of the admin to see that individual group.
class CustomUserAdmin(UserAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.filter(groups__name=request.user.group_admin_name)
If you want them filter on all groups, but one group at a time, then the admin has the list_filter property.
class CustomUserAdmin(UserAdmin):
list_filter = ('groups__name')
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter
Related
I have a Device model that has a many-to-many relationship to the built-in User object of Django. I'd like to override get_queryset() so that it only returns Device objects associated with the logged-in user.
models.py:
class Device(models.Model):
maintainers = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name="devices",
)
admin.py:
class DeviceAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(maintainers=request.user)
However, this code still shows all Device objects in my views defined in views.py, even if it is not associated with the logged-in user.
I've also tried maintainers__contains=request.user but the problem persists. What am I doing wrong? How do I correctly filter the QuerySet?
I mistakenly thought that get_queryset() would apply to all views within the Django application, including views defined in views.py. However overriding get_queryset() in admin.py only changes the view for the admin dashboard/console.
In this case, qs.filter(maintainers=request.user) correctly filters the device list in the admin console (if the user is a staff member and is allowed to access the admin console).
For anyone wishing to filter the model in views.py, add the following to your views.py file:
class DeviceView(LoginRequiredMixin, ListView):
# ...
def get_queryset(self):
return Device.objects.filter(maintainers=self.request.user)
I need to create Django model that couldn't by admin, but he should be avialable to see it.
It's content will be input from site.
How can I do it?
Basically if you want to disable the editability of the model you may want to make use of Django Admin's permission framework, like this:
class PersonAdmin
def has_change_permission(self, request, obj=None):
# only allows superusers to edit
return request.user.is_superuser
You may also want to try the readonly_field like:
class PersonAdmin
readonly_fields = ('name','sex',)
But the problem of doing this is that you will see the save buttons on the editing page despite that nothing is allowed to be changed, which is probably not what you want
Designate that it should be read only
In your Model Admin, you can specify that certain fields are not to be changed.
class ProfileAdmin(admin.ModelAdmin):
readonly_fields = ('source', 'campaign')
Just put that in your admin.py and then when you got to register your site, use this:
admin.site.register(Profile, ProfileAdmin)
instead of what you are probably currently using, which would be
admin.site.register(Profile)
You can list the fields you want on both fields and readonly_fields.
class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title')
readonly_fields = ('name', 'title')
I am working with a blog site. I want to add some feature that like admin filter post can modify only that user added. I want to use Django builtin LogEntry model.
Any can help me?
You could override the ModelAdmin's get_queryset method along the following lines:
from django.contrib.admin.models import ADDITION
from django.contrib import admin
class MyModelAdmin(admin.ModelAdmin):
# ...
def get_queryset(self, request):
qs = super(MyModelAdmin, self).get_queryset(request)
ct = ContentType.objects.get_for_model(MyModel)
qs = qs.filter(id__in=list(
LogEntry.objects.filter(content_type=ct,
action_flag=admin.models.ADDITION,
user=request.user)\
.values_list('object_id', flat=True)))
return qs
This will narrow down the objects the admin has access to the ones created by the currently logged in user.
I have a django site with lots of models and forms. I have many custom forms and formsets and inlineformsets and custom validation and custom querysets. Hence the add model action depends on forms that need other things, and the 'add model' in the django admin throughs a 500 from a custom queryset.
Is there anyway to disable the 'Add $MODEL' functionality for a certain models?
I want /admin/appname/modelname/add/ to give a 404 (or suitable 'go away' error message), I don't want the 'Add $MODELNAME' button to be on /admin/appname/modelname view.
Django admin provides a way to disable admin actions (http://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#disabling-actions) however the only action for this model is 'delete_selected'. i.e. the admin actions only act on existing models. Is there some django-esque way to do this?
It is easy, just overload has_add_permission method in your Admin class like so:
class MyAdmin(admin.ModelAdmin):
def has_add_permission(self, request, obj=None):
return False
I think this will help you..
below code must be in admin.py file
#admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
list_display = ('name', )
list_filter = ('name', )
search_fields = ('name', )
list_per_page = 20
# This will help you to disbale add functionality
def has_add_permission(self, request):
return False
# This will help you to disable delete functionaliyt
def has_delete_permission(self, request, obj=None):
return False
In additon to the above as posted by
# This will help you to disable change functionality
def has_change_permission(self, request, obj=None):
return False
By default syncdb creates 3 security permissions for each model:
Create (aka add)
Change
Delete
If your logged in as Admin, you get EVERYTHING no matter what.
But if you create a new user group called "General Access" (for example) then you can assign ONLY the CHANGE and DELETE permissions for all of your models.
Then any logged in user that is a member of that group will not have "Create" permission, nothing related to it will show on the screen.
Just copy code from another answer
# In admin
# make the related field can't be added
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
form.base_fields['service'].widget.can_add_related = False
return form
In my case I use inline
# In inline formset e.g. admin.TabularInline
# disable all
def get_formset(self, request, obj=None, **kwargs):
formset = super().get_formset(request, obj, **kwargs)
service = formset.form.base_fields['service']
service.widget.can_add_related = service.widget.can_change_related = service.widget.can_delete_related = False
return formset
in service = formset.form.base_fields['service']
base_fields is the fields defined in model
if defined in the form use:
product = formset.form.declared_fields['product']
see also
This is a too much delayed answer; Just posting this as if anyone is finding the same solution.
In admin.py file you can do the following:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = '__all__'
class MyModelAdmin(admin.ModelAdmin):
form = QuestionTrackAdminForm
list_display = ['title', 'weight']
readonly_fields = ['title', 'weight']
admin.site.register(MyModel, MyModelAdmin)
Here, "readonly_fields" does the magic. Thanks.
In the django admin you can set the search_fields for the ModelAdmin to be able to search over the properties given there. My model class has a property that is not a real model property, means it is not within the database table. The property relates to another database table that is not tied to the current model through relations.
But I want to be able to search over it, so I have to somehow customize the query the admin site creates to do the filtering when the search field was filled - is this possible and if, how?
I can query the database table of my custom property and it then returns the ids of the model classes fitting the search. This then, as I said, has to flow into the admin site search query.
Thanks!
Since django 1.6, you can customize the search by defining a get_search_results method in your ModelAdmin subclass.
It is well explained in django documentation. The following example is copied from this doc.
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'age')
search_fields = ('name',)
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super(PersonAdmin, self).get_search_results(request, queryset, search_term)
try:
search_term_as_int = int(search_term)
queryset |= self.model.objects.filter(age=search_term_as_int)
except:
pass
return queryset, use_distinct
You should use search_fields = ['foreign_key__related_fieldname']
like search_fields = ['user__email'] in the admin class that extends admin.ModelAdmin
read more here
this might can help
search_fields = ['foreign_key__related_fieldname']
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields