带有viewset-router查询集过滤的Django REST Framework

Ale*_*dor 5 python django django-rest-framework

我正在使用Django 1.7并且我使用REST Framework,我已经实现了一个简单的API来获取模型中的所有对象,但我想过滤放置外部对象值的结果.

例如,实际上我可以拥有一个包含此URL的对象列表

http://localhost:8000/api/ocompradetalle
Run Code Online (Sandbox Code Playgroud)

如果我只想要一个,我只能像这样放PK(PrimaryKey)

http://localhost:8000/api/ocompradetalle/1/
Run Code Online (Sandbox Code Playgroud)

我想更改主键以按外部字段值进行过滤,我的意思是,我有一个文档(OCompra),其值为"folio"字段,此文档将包含许多详细信息(OCompraDetalle),因此,我想要能够放这样的东西:

http://localhost:8000/api/ocompradetalle/F2033
Run Code Online (Sandbox Code Playgroud)

"F2033"是一个"作品集"值,响应应该在"作品集"字段中为我带来OCompra对象的所有细节.

这就是我现在所拥有的.

urls.py >>我有接收ViewSets的路由器

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)),
)
Run Code Online (Sandbox Code Playgroud)

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')
Run Code Online (Sandbox Code Playgroud)

views.py

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


class OCompraViewSet(viewsets.ModelViewSet):
    queryset = OCompra.objects.all()
    serializer_class = OCompraSerializer
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

Joe*_*eyP 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"
Run Code Online (Sandbox Code Playgroud)

所以:

http://localhost:8000/api/ocompradetalle/1/
Run Code Online (Sandbox Code Playgroud)

将为您提供ocompradetalle对象,其中ocompradetalle.ocompra.folio等于1.这仅在映射是一对一或作品集列具有唯一索引时才有效.详细信息视图不能返回多个对象

如果您希望按联接表上的列进行筛选,则可以执行以下操作:

http://localhost:8000/api/ocompradetalle/?ocompra__envio=blah
Run Code Online (Sandbox Code Playgroud)

你会得到所有ocompradetalle.ocompra.envio = blah的ocompradetalles