【问题标题】:How can I get a list of "ProductoSeralizer" in my "UsuarioSerializer" Django如何在我的“Usuario Serializer”Django 中获取“ProductoSeralizer”列表
【发布时间】:2021-06-19 12:59:19
【问题描述】:

我需要每个用户订购的产品,比如在“UsuarioSerializer”中我想放置一个字段“productos”,它是“ProductoSeralizer”的列表,但模型“Usuario”没有直接关系使用“ProductoSeralizer”,所以当我尝试时它给我一个错误,如何解决这个问题?我需要这样的 JSON 响应:

[
    {
        "id": 1,
        "cantidad_de_productos": 12,
        "fecha": "2021-03-21T06:26:26.981487Z",
        "correo": "user1@email.com",
        "password": "pass",
        "productos" : [
            {},
            {}
        ]
    },
    {
        "id": 2,
        "cantidad_de_productos": 0,
        "fecha": "2021-03-21T06:26:56.700399Z",
        "correo": "user2@email.com",
        "password": "pass",
        "productos" : [
            {},
            {}
        ]
    }
]

models.py

class Entidad(models.Model):
    fecha = models.DateTimeField(auto_now=True)
    class Meta:
        abstract = True

class Usuario(Entidad):
    correo = models.EmailField(unique=True)
    password = models.CharField(max_length=20)

    def __str__(self) -> str:
        return self.correo

class Orden(Entidad):
    solicitante = models.ForeignKey(Usuario, related_name='ordenes', on_delete=models.CASCADE)
    productos = models.ManyToManyField('Producto', through='Detalle')

class Producto(Entidad):
    nombre = models.CharField(max_length=20, unique=True)
    ordenes = models.ManyToManyField('Orden', through='Detalle')

    def __str__(self) -> str:
        return self.nombre

class Detalle(Entidad):
    cantidad = models.PositiveIntegerField()

    orden = models.ForeignKey(Orden, related_name='detalles', on_delete=models.CASCADE)
    producto = models.ForeignKey(Producto, related_name='detalles', on_delete=models.CASCADE)

序列化器.py

class ProductoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Producto
        fields = '__all__'

class ProductosUsuarioSerializer(serializers.ModelSerializer):
    cantidad = models.IntegerField()
    class Meta:
        model = Producto
        fields = '__all__'

class DetalleOrdenSerializer(serializers.ModelSerializer):
    class Meta:
        model = Detalle
        exclude = ['orden']

class OrdenSerializer(serializers.ModelSerializer):
    detalles = DetalleOrdenSerializer(many=True)
    class Meta:
        model = Orden
        exclude = ['productos']

    def create(self, validated_data):
        detalles_data = validated_data.pop('detalles')
        orden = Orden.objects.create(**validated_data)
        for detalle_data in detalles_data:
            Detalle.objects.create(orden=orden, **detalle_data)
        return orden

class DetalleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Detalle
        fields = '__all__'

class UsuarioSerializer(serializers.ModelSerializer):
    cantidad_de_productos = serializers.IntegerField()

    class Meta:
        model = Usuario
        fields = '__all__'

views.py

class Usuario(ListCreateAPIView):
    queryset = Usuario.objects.annotate(cantidad_de_productos=Coalesce(Sum('ordenes__detalles__cantidad'), 0))
    serializer_class = UsuarioSerializer

【问题讨论】:

    标签: django django-models django-rest-framework django-views django-serializer


    【解决方案1】:

    您可以将SerializerMethodField 字段添加到序列化程序。

    from models import Orden, Producto
    
    
    class UsuarioSerializer(serializers.ModelSerializer):
        cantidad_de_productos = serializers.IntegerField()
        productos = serializers.SerializerMethodField()
    
        class Meta:
            model = Usuario
            fields = '__all__'
    
        def get_productos(self, obj):
            ordenes = Orden.objects.filter(solicitante=obj.id)
            # get all product ids from orders
            product_ids = [product.id for orden in ordenes for product in orden.productos.all()]
            # find products (It does not matter if there are duplicate ids, it will not repeat products.)
            user_products = Producto.objects.filter(id__in=product_ids)
            # format the response
            products = [{
                'id': product.id,
                'name': product.nombre
            } for product in user_products]
            return products
    

    该方法被每个返回的用户调用

    【讨论】:

    • 谢谢它的工作:),但只有一个细节,它给了我重复的产品列表,我的意思是例如两倍于 id 1 的产品,有没有办法避免重复行?
    • 更新答案,我想现在可以了。
    猜你喜欢
    • 2021-11-16
    • 2015-12-24
    • 2015-10-29
    • 2016-06-14
    • 2020-02-09
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多