如何创建一个视图,该视图检索url中具有匹配主键的所有对象?

时间:2019-04-16 06:48:29

标签: python django django-rest-framework

我有两个形成一对多关系的模型。一个货盘具有与其关联的多个图像。

models.py

class Pallet(models.Model):

    pallet_id = models.IntegerField(primary_key=True)

    def __str__(self):
        return str(self.pallet_id)

    class Meta:
        ordering = ('pallet_id',)


class Image(models.Model):

    created = models.DateTimeField(auto_now_add=True)
    pallet = models.ForeignKey(Pallet, on_delete=models.CASCADE)
    image = models.FileField(upload_to="")

    def __str__(self):
        return str(self.created)

我正在尝试创建一个视图,在该视图中,我从URL中获取所有与特定的Pallet_id相关的图像。

serializers.py

class ImageSerializer(serializers.HyperlinkedModelSerializer):

    pallet = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Image
        fields = '__all__'

class PalletSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pallet
        fields = '__all__'

urls.py

urlpatterns = [
    url(r'^pallets/', include([
        url(r'^(?P<pk>[0-9]+)/$', views.PalletDetail.as_view(), name='pallet-detail'),
        ])),
]

我认为问题出在PalletDetail类的views.py中。我对如何基于URL的主键编写视图感到困惑。我尝试使用** kwargs ['pk'],但是使用它是否使它成为基于函数的视图?如果是这样,将基于类的视图和基于函数的视图混合会是不好的形式吗?如何从基于类的视图中获得类似的行为?

我真的很在意这里的观点:

views.py

class PalletDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Image.objects.prefetch_related('pallet').all()
    serializer_class = ImageSerializer

4 个答案:

答案 0 :(得分:0)

在基于函数的视图中 传递pk参数 示例:

def Example_function(request, pk):
    queryset = Model.objects.filter(id=pk)

在基于类的视图中 获取网址参数

pk = self.kwargs.get('pk')
queryset = Model.objects.filter(id=pk)

答案 1 :(得分:0)

您正在使用序列化程序,并以错误的方式查看。

您的PalletDetail视图的问题是您使用了错误的查询集。 queryset应该返回Pallet对象,因为查找将在该queryset上进行(默认查找字段为'pk')。另外,您还需要对Pallet使用序列化程序,因为它应该处理Pallet对象的数据。

class PalletDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Pallet.objects.all()
    serializer_class = PalletSerializer

答案 2 :(得分:0)

您是否尝试过filter_by()方法

queryset = Model.query.filter_by(id=pk).first()

答案 3 :(得分:0)

您正在以错误的方式进行操作。您要返回属于托盘的图像列表,因此您需要的是图像的列表视图,而不是托盘详细视图。网址应如下所示:

/pallets/<pallet_id>/images/

通过这种方式,URL是自我描述的,并且按照REST标准,您可以轻松地看到您所请求的图像属于托盘而不是托盘本身

urls.py

urlpatterns = [
    url(r'^pallets/', include([
        url(r'^(?P<pallet_pk>[0-9]+)/images/$', views.PalletImagesListView.as_view(), name='pallet-images-list'),
        ])),
]

在视图中,您必须覆盖get_queryset()方法,以便它仅返回指定托盘的图像

class PalletImagesListView(generics.ListAPIView):
    serializer_class = ImageSerializer

    def get_queryset(self):
        return Image.objects.prefetch_related('pallet').filter(pallet__pk=self.kwargs.get('pallet_pk'))

因此,现在您可以使用/pallets/1/images/

请求第一个托盘的图像