Django REST Framework中的视图集路由查询集过滤

5 投票
1 回答
7993 浏览
提问于 2025-04-30 00:12

我正在使用Django 1.7,并且在使用REST框架。我已经实现了一个简单的API,可以获取模型中的所有对象,但我想通过外键的值来过滤结果。

举个例子,现在我可以通过这个网址获取对象的列表:

http://localhost:8000/api/ocompradetalle

如果我只想要一个对象,我只能像这样输入主键(PrimaryKey):

http://localhost:8000/api/ocompradetalle/1/

我想把主键改成通过外键字段的值来过滤。我是说,我有一个文档(OCompra),它的“folio”字段有一个值,这个文档会有很多细节(OCompraDetalle),所以我想能够输入类似这样的内容:

http://localhost:8000/api/ocompradetalle/F2033

这里的“F2033”是一个“folio”的值,响应应该返回所有在“folio”字段中有这个值的OCompra对象的细节。

这就是我目前的情况。

urls.py >> 我有一个路由器,它负责处理视图集。

from rest_framework import routers
from inventario_rfid.views import OCompraViewSet, OCompraDetalleViewSet
from administracion.views import ProductoViewSet

router = routers.DefaultRouter()
router.register(r'ocompra',OCompraViewSet)
router.register(r'ocompradetalle',OCompraDetalleViewSet)
router.register(r'producto',ProductoViewSet)

urlpatterns = patterns('',
...
#APIS
url(r'^api/',include(router.urls)),
)

serializers.py

from rest_framework import serializers
from administracion.serializers import ProductoSerializer
from .models import OCompra, OCompraDetalle

class OCompraSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = OCompra
        fields = ('folio','codigo_proveedor','nombre_proveedor','status','fecha','subtotal','iva','envio',
                  'otro','total',)

class OCompraDetalleSerializer(serializers.HyperlinkedModelSerializer):
    producto = ProductoSerializer(many=False)
    ocompra = OCompraSerializer(many = False) << I WANT TO FILTER BY THIS (ocompra__folio)
    class Meta:
        model = OCompraDetalle
        fields = ('ocompra','producto','cantidad_ordenada','cantidad_recibida','fecha_entrega','precio','epc')

views.py

class OCompraDetalleViewSet(viewsets.ModelViewSet):
    queryset = OCompraDetalle.objects.all()
    serializer_class = OCompraDetalleSerializer


class OCompraViewSet(viewsets.ModelViewSet):
    queryset = OCompra.objects.all()
    serializer_class = OCompraSerializer

models.py

class OCompra(models.Model):
    folio = models.CharField(max_length=15)
    codigo_proveedor = models.CharField(max_length=15)
    nombre_proveedor = models.CharField(max_length=100)
    status = models.IntegerField(default=0)
    fecha = models.DateTimeField(auto_now_add=True)
    usuario = models.ForeignKey(User)
    subtotal = models.DecimalField(default=0,decimal_places=2, max_digits=20)
    iva = models.DecimalField(default=0,decimal_places=2, max_digits=20)
    envio = models.DecimalField(default=0,decimal_places=2, max_digits=20)
    otro = models.DecimalField(default=0,decimal_places=2, max_digits=20)
    total = models.DecimalField(default=0,decimal_places=2, max_digits=20)
    def __unicode__(self):
        return self.folio

class OCompraDetalle(models.Model):
    ocompra = models.ForeignKey(OCompra,related_name='detalles')
    producto = models.ForeignKey(Producto)
    cantidad_ordenada = models.DecimalField(default=0,decimal_places=2, max_digits=10)
    cantidad_recibida = models.DecimalField(default=0,decimal_places=2, max_digits=10)
    fecha_entrega = models.DateField(blank=True,null=True)
    precio = models.DecimalField(default=0,decimal_places=2, max_digits=10)
    epc = models.CharField(max_length=25,null=True,blank=True)
暂无标签

1 个回答

6

好的,如果我理解没错的话,你想要对一系列OCompraDetalle对象进行筛选,同时还希望能根据一个关联表(Ocompra)中的某个字段来设置查找值。这个视图集可以同时满足这两个需求。

from rest_framework import filters
OCompraDetalleViewSet(viewsets.ModelViewSet):
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('precio','ocompra__envio')

    serializer_class = OCompraDetalleSerializer
    queryset = OCompraDetalle.objects.all()
    lookup_field = "ocompra__folio"

那么:

http://localhost:8000/api/ocompradetalle/1/

这段代码会给你返回oCompradetalle对象,其中oCompradetalle.ocompra.folio等于1。这个方法只有在一对一映射的情况下有效,或者说folio这一列有唯一索引。因为详细视图不能返回多个对象。

如果你想根据关联表中的某一列进行筛选,可以这样做:

http://localhost:8000/api/ocompradetalle/?ocompra__envio=blah

这样你就能得到所有oCompradetalle对象,其中oCompradetalle.ocompra.envio等于某个值。

撰写回答