Django REST框架补丁请求使用查询而不是ID或PK
我有一个建筑模型,我已经为它创建了序列化程序和ModelViewSet 我可以通过发送补丁请求并指定模型ID来更新模型,如下所示:Django REST框架补丁请求使用查询而不是ID或PK,django,django-rest-framework,Django,Django Rest Framework,我有一个建筑模型,我已经为它创建了序列化程序和ModelViewSet 我可以通过发送补丁请求并指定模型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"
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,而是知道它希望更新的模型的属性
视图.py
class APIBuildingsViewSet(viewsets.ModelViewSet):
queryset = Building.objects.all()
serializer_class = BuildingSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name', 'address']
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
class BuildingSerializer(serializers.ModelSerializer):
class Meta:
model = Building
fields = ('building_id', 'name', 'address', 'user_id')
router = DefaultRouter()
router.register(r'buildings', views.APIBuildingsViewSet, base_name='buildings')
urlpatterns = [
url(r'^api/', include(router.urls)),
]
型号.py
class APIBuildingsViewSet(viewsets.ModelViewSet):
queryset = Building.objects.all()
serializer_class = BuildingSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name', 'address']
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
class BuildingSerializer(serializers.ModelSerializer):
class Meta:
model = Building
fields = ('building_id', 'name', 'address', 'user_id')
router = DefaultRouter()
router.register(r'buildings', views.APIBuildingsViewSet, base_name='buildings')
urlpatterns = [
url(r'^api/', include(router.urls)),
]
序列化程序.py
class APIBuildingsViewSet(viewsets.ModelViewSet):
queryset = Building.objects.all()
serializer_class = BuildingSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name', 'address']
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
class BuildingSerializer(serializers.ModelSerializer):
class Meta:
model = Building
fields = ('building_id', 'name', 'address', 'user_id')
router = DefaultRouter()
router.register(r'buildings', views.APIBuildingsViewSet, base_name='buildings')
urlpatterns = [
url(r'^api/', include(router.urls)),
]
url.py
class APIBuildingsViewSet(viewsets.ModelViewSet):
queryset = Building.objects.all()
serializer_class = BuildingSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name', 'address']
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
class BuildingSerializer(serializers.ModelSerializer):
class Meta:
model = Building
fields = ('building_id', 'name', 'address', 'user_id')
router = DefaultRouter()
router.register(r'buildings', views.APIBuildingsViewSet, base_name='buildings')
urlpatterns = [
url(r'^api/', include(router.urls)),
]
您可以在模型视图集中设置您的:
class APIBuildingsViewSet(viewsets.ModelViewSet):
queryset = Building.objects.all()
serializer_class = BuildingSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name', 'address']
lookup_field = 'name'
然后,您可以使用建筑物名称访问详细路线:/api/v1/buildings/hospital/
让客户先查找id有什么不对?然后他们可以决定如何处理多个建筑物同名的情况。这种方法没有错。我只是希望有一种方法可以让客户端用一个API请求而不是两个API请求来更新一栋建筑(第一个请求获得一栋建筑的pk,第二个请求更新该建筑)。我没有尝试过,但是你能将lookup\u field
设置为非唯一字段吗?看起来很危险。@RishiG我只是尝试一下,不,您不能对非唯一字段使用此方法。在尝试检索对象时(如果有多个对象的字段值相同),此方法将中断。