强制在 Django 中使用 PUT 请求只能更改某些属性
Posted
技术标签:
【中文标题】强制在 Django 中使用 PUT 请求只能更改某些属性【英文标题】:Enforce that only certain attributes can be changed using a PUT request in Django 【发布时间】:2021-01-20 11:07:14 【问题描述】:我想这样做,以便用户能够在我的 Django Rest API 中使用 PUT 请求仅更新某些属性。例如,如果我有以下模型并且只希望用户能够更新他们的名字和姓氏,我该怎么做?
models.py:
class User(models.Model):
email = models.EmailField('email address', unique = True)
first_name = models.TextField(max_length = 10)
last_name = models.TextField(max_length = 20)
(注意他们应该不能更改自动设置的“id”字段)
serializers.py:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'email', 'first_name', 'last_name']
views.py:
class SingleUser(APIView):
def put(self, request, user_id):
user = User.objects.get(pk = user_id)
serializer = UserEditSerializer(user, data = request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status = status.HTTP_200_OK)
return Response(serializer.errors, status = status.HTTP_400_BAD_REQUEST)
强制用户只能更改这些属性的子集的最佳方法是什么?
谢谢,格雷
【问题讨论】:
您可以定义一个序列化程序,它只包含您希望允许用户更改的字段,然后在处理put
请求时使用该序列化程序
【参考方案1】:
您可以在序列化程序上设置只读字段:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'email', 'first_name', 'last_name']
read_only_fields = ['id', 'email']
确保在 put 函数中将您的序列化程序设置为部分:
serializer = UserEditSerializer(user, data = request.data, partial=True)
您也可以完全省略序列化程序中的字段,这将使用户根本无法使用这些字段。
【讨论】:
【参考方案2】:创建一个单独的序列化器并使用它
# serializers.py
class UserPutSerializer(serializers.ModelSerializer): # new serializer class
class Meta:
model = User
fields = ['first_name', 'last_name'] # define required fields
#views.py
class SingleUser(APIView):
def put(self, request, user_id):
user = User.objects.get(pk=user_id)
serializer = UserPutSerializer(user, data=request.data) # use new serializer here
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
【讨论】:
Imo,这很快就会变得一团糟。如果您在模型中添加一个字段,现在您需要再更新一个序列化程序。如果您想要 put、post 和 get 请求的不同行为怎么办?在不知不觉中,您为每个模型维护了 3 个不同的序列化程序。 完全有可能创建一个序列化程序,根据您是创建、读取还是更新模型实例,其行为会有所不同。 是的,有可能。如果我的字段要求不是这样,我还将使用单个类,例如,id
和 username
用于HTTP GET,
id, and
first_name` 用于 HTTP POST,email
和 last_name
用于HTTP 放置。在这些情况下,我们不能依赖单个序列化程序类。 (是的,可以使用它"somehow",但是,我不认为它是 clean 针对每种情况处理不同字段的方法
除此之外,在这种情况下,我会坚持“单一职责原则”。 @NicoGriffioen 它还可以帮助我们非常轻松地“调试” 事情【参考方案3】:
您可以使用序列化程序的属性read_only_fields。
另一种方法是使用"serializer per action"
【讨论】:
以上是关于强制在 Django 中使用 PUT 请求只能更改某些属性的主要内容,如果未能解决你的问题,请参考以下文章
在前端 PUT 请求中返回内部服务器 500 错误 | Django Vue
Django REST framework框架之GET, POST, PUT, PATCH, DELETE等API请求接口设计
尽管字段具有“空白=真”,但 Django EmbeddedModelField 在执行 PUT 请求时说“此字段可能不是空白”