Python 仅允许用户访问一个字段-Django

Python 仅允许用户访问一个字段-Django,python,django,django-rest-framework,django-authentication,Python,Django,Django Rest Framework,Django Authentication,我正在为我的汽车共享应用程序使用Django Rest框架构建一个API。我想让非所有者用户有权在比赛中更新“参与者”字段,以便他们可以加入。其他字段应仅对所有者可用。我读到了,但我真的不知道如何实现它。这是我的模型: from django.db import models from django.contrib.auth.models import User class Race(models.Model): owner = models.ForeignKey("auth.Us

我正在为我的汽车共享应用程序使用Django Rest框架构建一个API。我想让非所有者用户有权在比赛中更新“参与者”字段,以便他们可以加入。其他字段应仅对所有者可用。我读到了,但我真的不知道如何实现它。这是我的模型:

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


class Race(models.Model):

    owner = models.ForeignKey("auth.User", related_name = 'races', on_delete=models.CASCADE)
    origin_long = models.DecimalField(max_digits=8, decimal_places=3)  
    origin_lat = models.DecimalField(max_digits=8, decimal_places=3)
    destination_long = models.DecimalField(max_digits=8, decimal_places=3)
    destination_lat = models.DecimalField(max_digits=8, decimal_places=3)
    start_time = models.TimeField(auto_now=False, auto_now_add=False)
    participants = models.ManyToManyField(User,blank=True)
    schedule = models.DurationField(blank=True,null=True)
    subs = models.ManyToManyField(User, related_name='subs',blank=True)
    cost = models.DecimalField(max_digits=5, decimal_places=2)


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

提前谢谢。

我认为Django默认情况下不需要字段级权限

但是我们可以通过
serializers.py
views.py
来调整和限制字段

views.py中

class RaceUpdateView(UpdateAPIView):
    lookup_field = 'pk'
    serializer_class = RaceUpdateSerializer
    queryset = Race.objects.all()
    permission_classes = [IsAuthenticated]
    model = Race

    def put(self, request, pk):
        try:
            try:
                race_obj = self.get_object()
            except Exception as error:
                context = {'error': "Race Id does not exist", 'success': "false", 'message': 'Race Id does not exist.'}
                return Response(context, status=status.HTTP_404_NOT_FOUND)

            #I don't know how you are checking owner. So i kept it this way.
            if request.user.id != race_obj.owner.id:
                #passing the fields which are to be used by the serializer.
                serializer = RaceUpdateSerializer(race_obj, data=request.data, partial=True, fields=('participants',))
            else:
                serializer = RaceUpdateSerializer(race_obj, data=request.data, partial=True)
            if serializer.is_valid():
                try:
                    serializer.save()
                except Exception as error:
                    context = {"success": False, "message": "Update Failed. %s" % str(error), "error": str(error)}
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)
                context = {"success": True, "message": "Updated Successful", "error": "", "data": serializer.data}
                return Response(context, status=status.HTTP_200_OK)
            context = {"success": False, "message": "Updated Failed, Invalid Input Data", "error": str(serializer.errors)}
            return Response(context, status=status.HTTP_400_BAD_REQUEST)
        except Exception as error:
            context = {'error': str(error), 'success': "false", 'message': 'Failed To Update Race.'}
            return Response(context, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class RaceUpdateSerializer(ModelSerializer):

    class Meta:
        model = Race
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super(RaceUpdateSerializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)
serializers.py中

class RaceUpdateView(UpdateAPIView):
    lookup_field = 'pk'
    serializer_class = RaceUpdateSerializer
    queryset = Race.objects.all()
    permission_classes = [IsAuthenticated]
    model = Race

    def put(self, request, pk):
        try:
            try:
                race_obj = self.get_object()
            except Exception as error:
                context = {'error': "Race Id does not exist", 'success': "false", 'message': 'Race Id does not exist.'}
                return Response(context, status=status.HTTP_404_NOT_FOUND)

            #I don't know how you are checking owner. So i kept it this way.
            if request.user.id != race_obj.owner.id:
                #passing the fields which are to be used by the serializer.
                serializer = RaceUpdateSerializer(race_obj, data=request.data, partial=True, fields=('participants',))
            else:
                serializer = RaceUpdateSerializer(race_obj, data=request.data, partial=True)
            if serializer.is_valid():
                try:
                    serializer.save()
                except Exception as error:
                    context = {"success": False, "message": "Update Failed. %s" % str(error), "error": str(error)}
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)
                context = {"success": True, "message": "Updated Successful", "error": "", "data": serializer.data}
                return Response(context, status=status.HTTP_200_OK)
            context = {"success": False, "message": "Updated Failed, Invalid Input Data", "error": str(serializer.errors)}
            return Response(context, status=status.HTTP_400_BAD_REQUEST)
        except Exception as error:
            context = {'error': str(error), 'success': "false", 'message': 'Failed To Update Race.'}
            return Response(context, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class RaceUpdateSerializer(ModelSerializer):

    class Meta:
        model = Race
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super(RaceUpdateSerializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)
这样,更新时只会使用从
视图.py调用的提到的字段

serializer = RaceUpdateSerializer(race_obj, data=request.data, partial=True, fields=('participants',))
它将完成你正试图完成的任务

注意-您也可以通过这种方式允许多个字段

serializer = RaceUpdateSerializer(race_obj, data=request.data, partial=True, fields=('field1','field2'))

您如何检查用户是否为所有者?是通过使用auth_组吗?现在我只允许用户修改自己的种族,其他人可以看到。这是我的职责。类ownerRorReadOnly(permissions.BasePermission):def具有对象权限(self、request、view、obj):if permissions.SAFE中的request.method\u方法:return True return obj.owner==request.userOk。因此,您修改了场景以调整您的需求。尽管我的代码适用于问题中提出的给定场景。你可以尝试并接受它,这样其他人就会发现它很有用。