Django

⌘K
  1. Home
  2. Django
  3. Django Rest Framework
  4. Partial Update Based on User Groups

Partial Update Based on User Groups

এই টিউটোরিয়ালে আমরা দেখাবো কিভাবে Django তে Device মডেলের উপর ভিত্তি করে গ্রুপ-ভিত্তিক পার্টিয়াল আপডেট (Partial Update) তৈরি করা যায়। এখানে Admin, Technician এবং অন্যান্য ব্যবহারকারীর জন্য আলাদা আলাদা ফিল্ড আপডেট করার অনুমতি থাকবে। আমরা কোম্পানি যাচাই করে দেখবো ব্যবহারকারীর অনুমতি আছে কিনা।

ধাপ ১: ডিভাইস মডেল তৈরি

প্রথমে আমরা একটি Device মডেল তৈরি করবো, যেখানে ডিভাইসের তথ্য যেমন location, description, ip_address, last_sync_time থাকবে। এই মডেলটি একটি Company মডেলের সাথে সম্পর্কিত থাকবে, যা দেখাবে যে ডিভাইসটি কোন কোম্পানির আওতায় আছে।

models.py

from django.db import models

class Company(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Device(models.Model):
    device_id = models.CharField(max_length=50, unique=True)  # ডিভাইসের আইডি
    location = models.CharField(max_length=100)  # ডিভাইসের অবস্থান
    description = models.TextField(null=True, blank=True)  # ডিভাইসের বর্ণনা
    ip_address = models.GenericIPAddressField(null=True, blank=True)  # ডিভাইসের আইপি এড্রেস
    last_sync_time = models.DateTimeField(null=True, blank=True)  # সর্বশেষ আপডেটের সময়
    serial_number = models.CharField(max_length=255, unique=True, null=True)  # সিরিয়াল নম্বর
    company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True)  # কোম্পানি সম্পর্ক

    def __str__(self):
        return f"{self.device_id} - {self.company}"

চাহিদা অনুযায়ী আমরা পরিবর্তন করবো যাতে:

  • Admin শুধুমাত্র location আপডেট করতে পারবে।
  • Technician শুধুমাত্র ip_address আপডেট করতে পারবে।
  • Stuff গ্রুপের ব্যবহারকারী অন্য সব ফিল্ড যেমন description, last_sync_time আপডেট করতে পারবে।

এই ধরনের পার্টিয়াল আপডেটের জন্য আমাদের get_allowed_fields_by_group() ফাংশন আপডেট করতে হবে এবং ফিল্ড আপডেটের নিয়মগুলো সংশোধন করতে হবে।

ধাপ ২: ভিউসেট তৈরি করা

DeviceViewSet ক্লাস ব্যবহার করে আমরা ডিভাইসের জন্য API তৈরি করবো। এখানে আমরা পার্টিয়াল আপডেটের জন্য partial_update() মেথড তৈরি করবো, যা ব্যবহারকারী এবং তার গ্রুপের উপর নির্ভর করবে।

views.py

from rest_framework import viewsets, status
from rest_framework.exceptions import ValidationError, NotFound
from rest_framework.permissions import IsAuthenticated
from .models import Device
from .serializers import DeviceSerializer
from .permissions import IsAdminOrTechnician
from rest_framework.response import Response

class DeviceViewSet(viewsets.ModelViewSet):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer
    permission_classes = [IsAuthenticated, IsAdminOrTechnician]

    def partial_update(self, request, *args, **kwargs):
        """ব্যবহারকারীর গ্রুপ এবং কোম্পানি অনুযায়ী ডিভাইস আপডেট করুন।"""
        instance = self.get_object()

        # ব্যবহারকারী এবং ডিভাইস একই কোম্পানির কিনা যাচাই করুন
        if instance.company.id != request.user.company.id:
            return Response({
                "error": "আপনার এই কোম্পানির অধীনে এই ডিভাইস আপডেট করার অনুমতি নেই।"
            }, status=status.HTTP_403_FORBIDDEN)

        # গ্রুপ অনুযায়ী অনুমোদিত ফিল্ড নির্ধারণ করা
        allowed_fields = self.get_allowed_fields_by_group(request.user)

        # অনুমোদিত ফিল্ড ফিল্টার করুন
        data = {key: value for key, value in request.data.items() if key in allowed_fields}

        if not data:
            return Response({
                "error": "কোন বৈধ ফিল্ড আপডেট করার জন্য দেওয়া হয়নি।"
            }, status=status.HTTP_400_BAD_REQUEST)

        # সিরিয়ালাইজার ব্যবহার করে পার্টিয়াল আপডেট করুন
        serializer = self.get_serializer(instance, data=data, partial=True)

        try:
            if serializer.is_valid(raise_exception=True):
                self.perform_update(serializer)
                return Response({
                    "message": "ডিভাইস সফলভাবে আপডেট হয়েছে।",
                    "data": serializer.data
                })

        except ValidationError as e:
            return Response({
                "error": "ভ্যালিডেশন ত্রুটি",
                "details": e.detail
            }, status=status.HTTP_400_BAD_REQUEST)
        except NotFound:
            return Response({
                "error": "ডিভাইস খুঁজে পাওয়া যায়নি।"
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                "error": "সার্ভার ত্রুটি।",
                "details": str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def get_allowed_fields_by_group(self, user):
        """ব্যবহারকারীর গ্রুপ অনুযায়ী অনুমোদিত ফিল্ড নির্ধারণ করুন।"""
        if user.groups.filter(name='Admin').exists():
            return ['location']  # Admin শুধুমাত্র location আপডেট করতে পারবে
        elif user.groups.filter(name='Technician').exists():
            return ['ip_address']  # Technician শুধুমাত্র ip_address আপডেট করতে পারবে
        elif user.groups.filter(name='Stuff').exists():
            return ['description', 'last_sync_time']  # Stuff গ্রুপ অন্যান্য ফিল্ড আপডেট করতে পারবে
        else:
            return []  # অন্যান্য গ্রুপের কোন অনুমতি নেই

এখানে কি হচ্ছে:

  1. কোম্পানি যাচাই করা:
    • instance.company.id এবং request.user.company.id মেলানো হচ্ছে যাতে ব্যবহারকারী এবং ডিভাইস একই কোম্পানির অধীনে থাকে।
  2. গ্রুপ অনুযায়ী অনুমোদিত ফিল্ড:
    • Admin গ্রুপ:
    • শুধুমাত্র location ফিল্ড আপডেট করতে পারবে।
    • Technician গ্রুপ:
    • শুধুমাত্র ip_address আপডেট করতে পারবে।
    • Stuff গ্রুপ:
    • description এবং last_sync_time ফিল্ড আপডেট করতে পারবে।
    • অন্যান্য ব্যবহারকারী:
    • যদি ব্যবহারকারী কোন অনুমোদিত গ্রুপের সদস্য না হয়, তাহলে কোন ফিল্ড আপডেট করার অনুমতি থাকবে না।
  3. সিরিয়ালাইজার ব্যবহার করা:
    • অনুমোদিত ফিল্ড ছেঁকে partial_update() মেথডের মাধ্যমে আপডেট করা হচ্ছে।

ধাপ ৩: পারমিশন আপডেট করা

permissions.py-তে IsAdminOrTechnician নাম পরিবর্তন করে গ্রুপ অনুযায়ী আলাদা ফিল্ড কন্ট্রোল করতে পারেন:

permissions.py

from rest_framework import permissions

class IsAdminOrTechnician(permissions.BasePermission):
    """
    কাস্টম পারমিশন যা যাচাই করবে ব্যবহারকারী 'Admin', 'Technician' বা 'Stuff' গ্রুপের সদস্য কিনা।
    """

    def has_permission(self, request, view):
        return request.user.groups.filter(name__in=['Admin', 'Technician', 'Stuff']).exists()

How can we help?