16:30 pm

PragetX

PPP

Bulk Permission Update.

Bulk Permission retrieval based on designation Id for all pages.
image

And Bulk Update Permission Using following schema.
image

  • This will create the permissions if doesn’t exists and update if permission exists.

Had to use a bunch of Serializers. I was never this great at it in Django. Main thing that pushed me to make it good was Swagger. A nice way to check apis in OpenAPI format.

class CustomPermissionUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Permission
        fields = ["can_view", "can_add", "can_edit", "can_delete"]
 
 
class PagePermissionsSerializer(serializers.ModelSerializer):
    permission = serializers.SerializerMethodField()
 
    class Meta:
        model = Page
        fields = ["id", "route_name", "priority", "permission"]
 
    def get_permission(self, obj):
        permission_obj = Permission.objects.filter(
            route=obj, designation=self.context["designation"]
        ).first()
        permission_obj_serializer = CustomPermissionUpdateSerializer(permission_obj)
        return permission_obj_serializer.data
 
 
class PagePermissionUpdateSerializer(serializers.Serializer):
    page_id = serializers.PrimaryKeyRelatedField(queryset=Page.objects.all())
    permission = CustomPermissionUpdateSerializer()
 
    def update(self, instance, validated_data):
        permission_data = validated_data.pop("permission")
        permission = instance.permission
 
        instance.route = validated_data.get("page_id", instance.page_id)
        instance.save()
 
        for attr, value in permission_data.items():
            setattr(permission, attr, value)
        permission.save()
        return instance
 
 
class DesignationPagePermissionSerializer(serializers.ModelSerializer):
    pages = serializers.SerializerMethodField()
    id = serializers.IntegerField(read_only=True)
    designation_name = serializers.CharField(read_only=True)
    description = serializers.CharField(read_only=True)
    is_active = serializers.BooleanField(read_only=True)
    created_at = serializers.DateTimeField(read_only=True)
    updated_at = serializers.DateTimeField(read_only=True)
 
    class Meta:
        model = Designation
        fields = [
            "id",
            "designation_name",
            "description",
            "is_active",
            "created_at",
            "updated_at",
            "pages",
        ]
 
    def get_pages(self, obj):
        pages = Page.objects.all()
        return PagePermissionsSerializer(
            pages, many=True, context={"designation": obj}
        ).data
 
 
class DesignationPagePermissionUpdateSerializer(serializers.ModelSerializer):
    pages = serializers.ListField(child=PagePermissionUpdateSerializer())
 
    class Meta:
        model = Designation
        fields = ["pages"]
 
    def update(self, instance, validated_data):
        pages_data = validated_data.pop("pages", [])
        updated_page_permission = []
        for page_data in pages_data:
            page = page_data["page_id"]
            original_permission = Permission.objects.filter(
                route=page, designation=instance
            ).first()
            updated_permission_data = page_data["permission"]
            updated_permission_data["route"] = page.id
            updated_permission_data["designation"] = instance.id
            if original_permission:
                updated_permission = PermissionCreateUpdateSerializer(
                    original_permission, data=updated_permission_data
                )
                if updated_permission.is_valid():
                    updated_permission.save()
                    updated_page_permission.append(
                        {"page": page, "permission": updated_permission}
                    )
                else:
                    raise serializers.ValidationError(updated_permission.errors)
            else:
                updated_permission = PermissionCreateUpdateSerializer(
                    data=updated_permission_data
                )
                if updated_permission.is_valid():
                    updated_permission.save()
                    updated_page_permission.append(
                        {"page": page, "permission": updated_permission}
                    )
        instance = DesignationPagePermissionSerializer(instance).data
        return instance

And then simple ModelViewSet

class DesignationBulkPermissionApi(ModelViewSet):
    queryset = Designation.objects.all()
    serializer_class = DesignationPagePermissionSerializer
    permission_classes = [IsAdminUser]
 
    def get_serializer_class(self):
        if self.action in ["create", "update"]:
            return DesignationPagePermissionUpdateSerializer
        return self.serializer_class
 
    @swagger_auto_schema(
        # request_body=DesignationPagePermissionSerializer,
        operation_description="Designation Bulk Permission",
    )
    def retrieve(self, request, *args, **kwargs):
        designation_obj = Designation.objects.get(id=kwargs.get("pk"))
        serializer = self.serializer_class(designation_obj)
        response = {
            "data": serializer.data,
            "status": status.HTTP_200_OK,
        }
        return Response(response, status=status.HTTP_200_OK)
 
    @swagger_auto_schema(
        request_body=DesignationPagePermissionUpdateSerializer,
        operation_description="Designation Bulk Permission",
    )
    def update(self, request, *args, **kwargs):
        designation_obj = Designation.objects.get(id=kwargs.get("pk"))
        serializer = self.get_serializer(designation_obj, data=request.data)
        if serializer.is_valid(raise_exception=True):
            serializer.update(designation_obj, serializer.validated_data)
            response = {
                "message": "Permission Updated",
                "status": status.HTTP_200_OK,
            }
 
            return Response(response, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Prevent Deletion of contents if they are foreign key in other objects.

Similar Logic as 11th March, Monday, 2024 for any models Category, Sub category, company, product, route, shop, designation, user. If they are foreignkey in any other obeject. Prevent deletion of it.

For all model viewset same logic implemented.

    def destroy(self, request, *args, **kwargs):
        data = self.get_serializer(self.get_object(request)).data
        obj_exists = Model.objects.filter(some_field=data['id']).exists()
        # e.g. 
        # shop_exists = Shop.objects.filter(salesman=data["id"]).exists()
        return (
            error_response_child_exists
            if obj_exists # or shop_exists or order_exists
            else super().destroy(request, *args, **kwargs)
        )

<<Yesterday Tomorrow>>


Links : Tags : Year : 2024 Month : March 24, March Date : 13th March, Wednesday, 2024, 13th March Category : Daily