【问题标题】:Django REST Framework PATCH request using a query instead of ID or PKDjango REST Framework PATCH 请求使用查询而不是 ID 或 PK
【发布时间】:2019-11-15 18:05:35
【问题描述】:

我有一个 Building 模型,为此我创建了一个序列化程序和 ModelViewSet。

我可以通过发送 PATCH 请求并指定 模型 ID 来更新模型,如下所示:

curl http://127.0.0.1/dashboard/api/v1/buildings/3/ \
--request PATCH \
--header "Content-Type: application/json" \
--data '{"name": "School","address": "123 Some Street","description": "A place to learn"}'

如何通过查询字段而不是传递模型 ID 来更新建筑模型?例如:

curl http://127.0.0.1/dashboard/api/v1/buildings/?name=hospital \
--request PATCH \
--header "Content-Type: application/json" \
--data '{"name": "School","address": "123 Some Street","description": "A place to learn"}'

注意,建筑物名称是唯一的!

此功能非常有用,因为客户端通常不知道模型 ID,而是知道它希望更新的模型的属性。


views.py

class APIBuildingsViewSet(viewsets.ModelViewSet):
    queryset = Building.objects.all()
    serializer_class = BuildingSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['name', 'address']

models.py

class Building(models.Model):
    building_id = models.AutoField('ID', auto_created=True, primary_key=True)
    name        = models.CharField('Name', max_length=125, null=True, blank=False, unique=True)
    address     = models.CharField('Address', max_length=256, null=False, blank=False)
    user_id     = models.ForeignKey('accounts.User', on_delete=models.CASCADE, default=1)

    def __str__(self):
        return self.name

serializers.py

class BuildingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Building
        fields = ('building_id', 'name', 'address', 'user_id')

urls.py

router = DefaultRouter()
router.register(r'buildings', views.APIBuildingsViewSet, base_name='buildings')

urlpatterns = [
    url(r'^api/', include(router.urls)),
]

【问题讨论】:

  • 让客户端先查id有什么问题?然后他们可以决定如何处理多个建筑物同名的情况。
  • 这种方法没有错。我只是希望有一种方法让客户端使用一个 API 请求而不是两个更新建筑物(第一个请求获取建筑物的 pk,第二个请求更新该建筑物)

标签: django django-rest-framework


【解决方案1】:

您可以在您的ModelViewSet 中设置您的lookup_field to be name

class APIBuildingsViewSet(viewsets.ModelViewSet):
    queryset = Building.objects.all()
    serializer_class = BuildingSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['name', 'address']
    lookup_field = 'name'

然后您可以使用建筑物name/api/v1/buildings/hospital/访问详细路线

【讨论】:

  • 我没试过,但是你能把lookup_field设置成一个非唯一的字段吗?看起来很危险。
  • @RishiG 我刚刚试了一下,不,您不能将此方法用于非唯一字段
  • 它会在尝试检索对象时中断(如果有多个对象具有相同的字段值)。
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
  • 2015-09-11
相关资源
最近更新 更多