Search code examples
pythondjangodjango-rest-framework

How to show permissions in django admin project?


I have a django app. And I try in the admin panel of django restrict user permissions with the AUTHENTICATION AND AUTHORIZATION tab.

But I noticed that something is missing in my existing django app on the AUTHENTICATION AND AUTHORIZATION tab.

Because I installed a clean install from django. And the AUTHENTICATION AND AUTHORIZATION tab looked like:

enter image description here

and the AUTHENTICATION AND AUTHORIZATION tab in my existing django app looks like:

enter image description here

So as you can see in my existing django app the right part is missing of the user permissions.

What I have done? Is checking the versions. And they are the same(clean version and exsting version)

I am using django version: 5.0.6. and the libraries

I checked the libraries installed with pip freeze of my exisiting version:

anyio==4.2.0
asgiref==3.7.2
attrs==23.1.0
azure-common==1.1.28
azure-core==1.29.6
azure-storage-blob==12.19.0
azure-storage-common==2.1.0
certifi==2023.7.22
cffi==1.15.1
charset-normalizer==3.2.0
click==8.1.7
colorama==0.4.6
coreapi==2.3.3
coreschema==0.0.4
cryptography==39.0.0
defusedxml==0.7.1
Django==5.0.6
django-allauth==0.52.0
django-cors-headers==3.10.1
django-dotenv==1.4.2
django-filter==23.2
django-storages==1.14.2
djangorestframework==3.14.0
drf-spectacular==0.26.4
drf-yasg==1.20.0
exceptiongroup==1.2.0
gunicorn==21.2.0
h11==0.14.0
idna==3.4
inflection==0.5.1
isodate==0.6.1
itypes==1.2.0
Jinja2==3.1.2
jsonschema==4.19.0
jsonschema-specifications==2023.7.1
Markdown==3.4.4
MarkupSafe==2.1.3
oauthlib==3.2.2
packaging==23.1
Pillow==10.0.0
psycopg2==2.9.7
pycparser==2.21
PyJWT==2.6.0
pyrsistent==0.19.3
python-dateutil==2.8.2
python3-openid==3.2.0
pytz==2023.3.post1
PyYAML==6.0.1
referencing==0.30.2
requests==2.31.0
requests-oauthlib==1.3.1
rpds-py==0.10.2
ruamel.yaml==0.17.32
ruamel.yaml.clib==0.2.7
six==1.16.0
sniffio==1.3.0
sqlparse==0.4.4
typing_extensions==4.7.1
tzdata==2023.3
uritemplate==4.1.1
urllib3==2.0.4
uvicorn==0.23.2
waitress==2.1.2

And part of settings.py file of the existing app:


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'drf_yasg',
    'corsheaders',
    'rest_framework.authtoken',
    'django_filters',
    'welAdmin',
    "accounts",
    "core",
    'drf_spectacular',
]

LOGOUT_REDIRECT_URL = "/"
ACCOUNT_LOGOUT_REDIRECT_URL = "/"


REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',

    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),

    'SWAGGER_SETTINGS': {
        'LOGIN_URL': 'rest_framework:login',
        'LOGOUT_URL': 'rest_framework:logout'
    }


}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'CET'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/


STATIC_URL = '/static/'
MEDIA_URL = '/media/'

STATIC_DIRS = [
    (BASE_DIR, 'static')
]
STATICFILES_DIRS = [BASE_DIR / 'static']


STATIC_ROOT = BASE_DIR / 'staticfiles/'
MEDIA_ROOT = BASE_DIR / 'media'

admin.py looks:

from django.contrib import admin, messages
from django.db import models
from django.forms import RadioSelect
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.safestring import mark_safe
from .models import Animal, Category
from .forms import SetCategoryForm





class AnimalAdmin(admin.ModelAdmin):
    fields = ['name', 'sort', 'category', 'klasse_name', 'cites', 'uis', 'pet_list',
              'description', "feeding", "housing", "care", "literature", 'images', 'img_preview']
    readonly_fields = ['img_preview', 'klasse_name']
    autocomplete_fields = ['category']

    list_display = ('name', 'category_link', 'description')

    search_fields = ['name', 'category__name']
    search_help_text = "Zoek in de namen of families"
    actions = ['set_category']
    action_form = SetCategoryForm
    ordering = ['id']
    formfield_overrides = {
        models.BooleanField: {"widget": RadioSelect(
            choices=[(True, "Ja"), (False, "Nee")])}
    }

    def response_add(self, request, obj, post_url_continue=None):
        if '_addanother' in request.POST:
            url = reverse("admin:WelzijnAdmin_animal_add")
            category_id = request.POST['category']
            qs = '?category=%s' % category_id
            return HttpResponseRedirect(''.join((url, qs)))
        if '_continue' in request.POST:
            return super(AnimalAdmin, self).response_add(request, obj, post_url_continue)
        else:
            return HttpResponseRedirect(reverse("admin:WelzijnAdmin_animal_changelist"))

    def response_change(self, request, obj, post_url_continue=None):
        if '_addanother' in request.POST:
            url = reverse("admin:WelzijnAdmin_animal_add")
            category_id = request.POST['category']
            qs = '?category=%s' % category_id
            return HttpResponseRedirect(''.join((url, qs)))
        if '_continue' in request.POST:
            return super(AnimalAdmin, self).response_change(request, obj)
        else:
            return HttpResponseRedirect(reverse("admin:WelzijnAdmin_animal_changelist"))

    @admin.action(description="Zet de familie van de geselecteerde n")
    def set_category(self, request, queryset):
        category = request.POST['familie']
        queryset.update(category=category)
        messages.success(
            request, '{0} animal(s) were updated'.format(queryset.count()))

    def category_link(self, obj):
        return mark_safe('<a href="{}">{}</a>'.format(
            reverse("admin:WelzijnAdmin_category_change",
                    args=[obj.category.pk]),
            obj.category.name
        ))
    category_link.short_description = 'Familie'


class CategoryAdmin(admin.ModelAdmin):
    fields = ['name', 'category', 'description', 'images', 'img_preview']
    readonly_fields = ['img_preview']
    autocomplete_fields = ['category']

    list_display = ('name', 'category_link',
                    'subcategories_link', 'animals_link')
    search_fields = ['name', 'category__name']
    search_help_text = "Zoek in de namen of families"
    actions = ['set_category']
    action_form = SetCategoryForm
    ordering = ['id']

    def response_add(self, request, obj, post_url_continue=None):
        if '_addanother' in request.POST:
            url = reverse("admin:WelzijnAdmin_category_add")
            category_id = request.POST['category']
            qs = '?category=%s' % category_id
            return HttpResponseRedirect(''.join((url, qs)))
        if '_continue' in request.POST:
            return super(CategoryAdmin, self).response_add(request, obj, post_url_continue)
        else:
            return HttpResponseRedirect(reverse("admin:WelzijnAdmin_category_changelist"))

    def response_change(self, request, obj, post_url_continue=None):
        if '_addanother' in request.POST:
            url = reverse("admin:WelzijnAdmin_category_add")
            category_id = request.POST['category']
            qs = '?category=%s' % category_id
            return HttpResponseRedirect(''.join((url, qs)))
        if '_continue' in request.POST:
            return super(CategoryAdmin, self).response_change(request, obj)
        else:
            return HttpResponseRedirect(reverse("admin:WelzijnAdmin_category_changelist"))

    @admin.action(description="Zet de familie van de geselecteerde families")
    def set_category(self, request, queryset):
        category = request.POST['familie']
        queryset.update(category=category)
        messages.success(
            request, '{0} categories were updated'.format(queryset.count()))

    def category_link(self, obj):
        if obj.category:
            return mark_safe('<a href="{}">{}</a>'.format(
                reverse("admin:WelzijnAdmin_category_change",
                        args=[obj.pk]),
                obj.category
            ))
        return None
    category_link.short_description = 'Familie'

    def subcategories_link(self, obj):
        if obj.subcategories.exists():
            return mark_safe('<a href="{}">{}</a>'.format(
                reverse("admin:WelzijnAdmin_category_changelist") +
                f"?category={obj.id}",
                "Subgroepen"
            ))
        return None
    subcategories_link.short_description = "Subgroepen"

    def animals_link(self, obj):
        if obj.animals.exists():
            return mark_safe('<a href="{}">{}</a>'.format(
                reverse("admin:WelzijnAdmin_animal_changelist") +
                f"?category={obj.id}",
                ""
            ))
        return None
    animals_link.short_description = "in groep"


admin.site.register(Animal, AnimalAdmin)
admin.site.register(Category, CategoryAdmin)

I have also a accounts app. and the admin.py looks like:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .models import Account

# Register your models here.


class AccountAdmin(UserAdmin):
    list_display = (
        "email",
        "first_name",
        "last_name",
        "username",
        "last_login",
        "date_joined",
        "is_active",
    )
    list_display_links = ("email", "first_name", "last_name")
    filter_horizontal = ('groups', 'user_permissions',)
    readonly_fields = ("last_login", "date_joined")
    ordering = ("-date_joined",)

    filter_horizontal = ()
    list_filter = ()
    fieldsets = ()


# Register your models here.
admin.site.register(Account, AccountAdmin)
# admin.site.register(Account, AccountAdmin)

Question: How to show the choosen user persmissions in the existing django app?


Solution

  • You unset the filter_horizontal with filter_horizontal = (), remove that line:

    class AccountAdmin(UserAdmin):
        list_display = (
            'email',
            'first_name',
            'last_name',
            'username',
            'last_login',
            'date_joined',
            'is_active',
        )
        list_display_links = ('email', 'first_name', 'last_name')
        filter_horizontal = (
            'groups',
            'user_permissions',
        )
        readonly_fields = ('last_login', 'date_joined')
        ordering = ('-date_joined',)
    
        # filter_horizontal = ()  🖘 remove
        list_filter = ()
        fieldsets = ()