Home > Blockchain >  Need to restrict the access for staff users to view and edit only their inputted data in django admi
Need to restrict the access for staff users to view and edit only their inputted data in django admi

Time:03-03

I need to restrict the access in the admin page like if a staff user is logging in the admin they need to see only their entry data's and can able to add or delete their data in the admin panel.

As I tried the below code in the admin.py still I could able to view and delete everyone's data.

Admin.py


admin.site.site_header = "Inhouse Project Management"
admin.site.site_title = "TimeSheet Admin Portal"
admin.site.index_title = "TimeSheet Administration"

TokenAdmin.raw_id_fields = ['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(user=request.user)

#Admin SuperUser
@admin.register(User)

class UserAdmin(ImportExportModelAdmin):
    list_display = ('id','employee_name','email','billable_and_non_billable','designation')
    search_fields = ['employee_name']
    pass

@admin.register(Project)

class ProjectAdmin(ImportExportModelAdmin):
    list_display = ('id','project_name','client','start_date','end_date')
    search_fields = ['project_name']
    pass

Urls.py

urlpatterns = [
    path('', TemplateView.as_view(template_name="social_app/index.html")), #social_app/index.html
    path('admin/', admin.site.urls),         #admin api
    path('api/',include(router.urls)),          #api
    path('accounts/', include('allauth.urls')),       #allauth
    re_path('rest-auth/', include('rest_auth.urls')),    #rest_auth
    path('api-auth/', include('rest_framework.urls')),
    re_path('rest-auth/registration/', include('rest_auth.registration.urls')),
    #path('api-token-auth/', views.obtain_auth_token),
    #path('api-token-auth/',CustomAuthToken.as_view()),
    #path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('auth/login/',TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('conso/',view),
    path('chaining/', include('smart_selects.urls')),
]

models.py

class User(models.Model):
    
    
    BLOOD_GROUP_CHOICES = (
        
        ('a ','A '),
        ('a-','A-'),
        ('b ','B '),
        ('b-','B-'),
        ('ab ','AB '),
        ('ab-','AB-'),
        ('o ','O '),
        ('o-','O-')
        
    )
    
    
    BILLABLE_and_NON_BILLABLE_CHOICES=(
        
        
        ('Billable','Billable'),
        ('Non-Billable','Non-Billable')
    )



    employee_name = models.CharField(max_length=50)
    dob=models.DateField(max_length=8) 
    email=models.EmailField(max_length=254,default=None) 
    pancard=models.CharField(max_length=25,default=None)
    aadhar=models.CharField(max_length=20,default=None)
    personal_email_id=models.EmailField(max_length=254,default=None)
    phone = PhoneField(blank=True)
    emergency_contact_no=models.IntegerField(default=None)
    emergency_contact_name=models.CharField(max_length=100,null=True)
    relation=models.CharField(max_length=25,default=None)
    blood_group=models.CharField(max_length=25,choices=BLOOD_GROUP_CHOICES,null=True)  
    designation=models.ForeignKey(Designation,on_delete=CASCADE,related_name="designation")
    billable_and_non_billable=models.CharField(max_length=25,choices=BILLABLE_and_NON_BILLABLE_CHOICES,default='Billable')
    joining_date=models.DateField(max_length=15,null=True)
    relieving_date=models.DateField(max_length=15,null=True)
    
    class Meta:
        db_table ='User'
        
        
    def __str__(self):
        return self.employee_name

serializers.py

class UserSerializers(serializers.ModelSerializer):
    
    #Email Notification
    def create(self, validate_data):
        subject = 'Your account was activated'
        plain_message = 'SAMPLE TEXT'
        from_email = '[email protected]'
        to_email = validate_data['email']
        EmailThread(subject, plain_message, from_email, to_email).start()
        return User.objects.create(**validate_data)

I need to restrict the access for users to view and edit only their data in the admin panel. I dont know what needs to be updated to get that worked. Kindly help to resolve this issue.

Updated code as per the answer

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

class UserAdmin(BaseUserAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        user = request.user
        return qs if user.is_staff else qs.filter(user=user)

'''class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if self.request.user.is_staff:
            return qs
        print(request.user)
        #return qs.filter(user=request.user)'''

#Admin SuperUser
@admin.register(User)

class UserAdmin(ImportExportModelAdmin):
    list_display = ('id','employee_name','email','billable_and_non_billable','designation')
    search_fields = ['employee_name']
    pass

Job model where the employee_name is linked under user field from the user model

class Job(models.Model):
    
    job_name=models.CharField(max_length=50)
    client=models.ForeignKey(Client,on_delete=CASCADE,related_name='client',default=None)
    project = ChainedForeignKey(Project,chained_field="client", chained_model_field="client",show_all=False, auto_choose=True, sort=True)
    user=models.ForeignKey(User,on_delete=CASCADE,related_name='user',default=None)
    hours=models.TimeField(null=True)
    start_date = models.DateTimeField(max_length=10)
    end_date=models.DateTimeField(max_length=10)

CodePudding user response:

First you've to create a class that will handle displaying objects to respective user

class StaffAdmin(admin.ModelAdmin):

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(user=request.user)

then you've to register this class with your model where you want to add this functionality eg. if you want to display project of perticular user you've to register this class with Project model like this

admin.site.register(Project, StaffAdmin)

Note: If you've logged in as staff make sure you've given permission to your staff to (view, add, update, delete) projects or it will raise PermissionDenied error check how to add permissions to user. You may want to add user's permission programaticlly then check default-permissions[Django-doc]

CodePudding user response:

Create a custom user model, i will put my code hope that help!

Crm views

from django.shortcuts import reverse
from .models import Lead
from .leadforms import LeadForm, CreatingUser
from django.views import generic
from django.core.mail import send_mail
from django.contrib.auth.mixins import LoginRequiredMixin

# Create your views here.
class signup(LoginRequiredMixin, generic.CreateView):
    template_name = 'registration/signup.html'
    form_class = CreatingUser

    def get_success_url(self):
        return reverse("LogInPage")

class leads(LoginRequiredMixin, generic.ListView):
    template_name = "crm/leads.html"
    queryset = Lead.objects.all()
    context_object_name = "leads"

class leadetails(LoginRequiredMixin, generic.DetailView):
    template_name = 'crm/leadetails.html'
    queryset = Lead.objects.all()
    context_object_name = "lead"

class leadcreate(LoginRequiredMixin, generic.CreateView):
    template_name = 'crm/leadcreate.html'
    form_class = LeadForm

    def get_success_url(self):
        return reverse("LeadsPage")

    def form_valid(self, form):
        send_mail(
            subject = "A lead Has been Created!",
            message = f"Agent is :{requset.user.username}",
            from_email = "[email protected]",
            recipient_list= ["[email protected]"]
        )
        return super(leadcreate, self).form_valid(form)

class leadupdate(LoginRequiredMixin, generic.UpdateView):
    template_name = 'crm/leadupdate.html'
    form_class = LeadForm
    queryset = Lead.objects.all()

    def get_success_url(self):
        return reverse("LeadsPage")

class leadelete(LoginRequiredMixin, generic.DeleteView):
    template_name = 'crm/leadelete.html'
    queryset = Lead.objects.all()

    def get_success_url(self):
        return reverse("LeadsPage")

crm urls

from django.urls import path
from . import views
from django.contrib.auth.views import LoginView, LogoutView

urlpatterns = [
    path('', LoginView.as_view(), name="LogInPage"),
    path('logout', LogoutView.as_view(), name="LogOutPage"),
    path('signup', views.signup.as_view(), name="SignUpPage"),
    path('leads', views.leads.as_view(), name="LeadsPage"),
    path('leads/<int:pk>', views.leadetails.as_view(), name="Leadetails"),
    path('leads-create', views.leadcreate.as_view(), name="LeadCreate"),
    path('leads/<int:pk>-update', views.leadupdate.as_view(), name="Leadupdate"),
    path('leads/<int:pk>-delete', views.leadelete.as_view(), name="Leadelete"),
]

crm models

from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.
class User(AbstractUser):
    is_organisor = models.BooleanField(default=True)
    is_agent = models.BooleanField(default=False)

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.user.username

class Agent(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    organisation = models.ForeignKey(UserProfile, on_delete=models.CASCADE)

    def __str__(self):
        return self.user.username

class Lead(models.Model):
    publish_date = models.DateTimeField(auto_now_add=True)
    full_name = models.CharField(max_length=50)
    passport_no = models.CharField(max_length=11)
    email = models.CharField(max_length=90)
    number = models.CharField(max_length=15)
    agent = models.ForeignKey(Agent, null=True, blank=True,  on_delete=models.CASCADE)

    def __str__(self):
        return self.full_name

def UserCreateSignal(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

models.signals.post_save.connect(UserCreateSignal, sender=User)

Crm form

from django import forms
from .models import Lead
from django.contrib.auth.forms import UserCreationForm, UsernameField
from django.contrib.auth import get_user_model

# Create your forms hear.

User = get_user_model()

class LeadForm(forms.ModelForm):
    class Meta:
        model = Lead
        fields = (
            'full_name',
            'passport_no',
            'email',
            'number',
            'agent',
        )

class CreatingUser(UserCreationForm):
    class Meta:
        model = User
        fields = ("username",)
        field_classes = {'username': UsernameField}

Base html

<!DOCTYPE html>
<html lang="en">
{% load static %}
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %} {% endblock %}</title>
    <link rel="shortcut icon" href="{% static 'crm/images/favicon.ico' %}" type="image/x-icon">
    <link rel="stylesheet" href="{% static 'crm/css/styles.css' %}">
</head>
<body>
    {% if not request.user.is_authenticated %}
    {% else %}
    {% if request.user.is_organisor %}
    <a href="{% url 'SignUpPage' %}">Create a new user</a>
    <a href="{% url 'AgentsPage' %}">Agents</a>
    {% endif %}
    <a href="{% url 'LeadsPage' %}">Leads</a>
    {% endif %}
    {% if request.user.is_authenticated %}
    Welcome {{ request.user.username }}
    <a href="{% url 'LogOutPage' %}">Logout</a>
    {% else %}
    <a href="{% url 'LogInPage' %}">Login</a>
    {% endif %}
    {% block body %} {% endblock %}
</body>
</html>

you can assign different roles like is_organisor, is_agent in above code and you can restrict them from accessing and can edit in django admin

Reference images Permissions

2nd permission ref

Note: don't copy and past it's an incomplete code

  • Related