如何通过关系将字段从中间模型序列化为多对多的主模型?

时间:2018-08-08 11:40:12

标签: python json django python-3.x django-rest-framework

我在Django Rest Framework中使用django 2,并且具有以下模型:

class Product(models.Model):
    name = models.Charfield()
    description = models.TextField()


class ProductStorageCenter(models.Model):
    product_id = models.ForeignKey(Product)
    storage_center_id = models.ForeignKey(StorageCenter)
    quantity = models.IntegerField()


class StorageCenter(models.Model):
    name = models.Charfield()
    city = models.ForeignKey(City)
    products = models.ManyToManyField(Product, through="ProductStorageCenter")

我想知道每个StorageCenter中有哪些产品,以及该StorageCenter中可用产品的数量。 如何显示包含其所有产品的StorageCenter列表以及该StorageCenter的每种产品的数量?

JSON返回将如下所示:

[
    {   "id": 1,
        "name": "My Storage Center",
        "city": 1,
        "products": [
            {   
                "id": 1,
                "name": "My Product 1",
                "description": "My Product Description 1",
                "quantity": 200            
            },
            {
                "id": 2,
                "name": "My Product 2",
                "description": "My Product Description 2",
                "quantity": 500            
            }
        ]    
    },    
    {
        "id": 2,
        "name": "My Storage Center 2,
        "city": 2,
        "products": [
            {
                "id": 1,
                "name": "My Product 1",
                "description": "My Product Description 1",
                "quantity": 350            
            }
        ]    
    }
]

编辑:

现在我可以获得上面的JSON,但我认为这不是最佳解决方案。在My StorageCenterSerializer中,我获得具有功能的StorageCenter产品,而不仅仅是使用ProductSerializer。然后,我循环“产品”查询集,然后在该StorageCenter中检索该产品的数量。

现在是我的序列化器:

class ProductSerializer(serializers.ModelSerializer):

    quantity = serializers.IntegerField(read_only=True)

    class Meta:
        model = Product
        fields = ('id', 'name', 'description', 'quantity')


class StorageCenterSerializer(serializers.ModelSerializer):

    products = serializers.SerializerMethodField()


    class Meta:
        model = StorageCenter
        fields = ('id', 'name', 'city', 'products')


    def get_products(self, obj):
        products = Product.objects.filter(productstoragecenter__storage_center_id = obj.id)

        for product in products:

            psc = ProductStorageCenter.objects.get(storage_center_id = obj.id, product_id = product.id)
            product.quantity = psc.quantity

        serializer = ProductSerializer(products, many=True)

        return serializer.data

2 个答案:

答案 0 :(得分:0)

您应将Nested relationshipsmany=True一起使用。

您没有发布序列化程序,因此这是DRF文档中的示例:

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ('order', 'title', 'duration')

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

序列化相册时。您将获得嵌套的音轨:

{
    'album_name': 'The Grey Album',
    'artist': 'Danger Mouse',
    'tracks': [
        {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
        {'order': 2, 'title': 'What More Can I Say', 'duration': 264},
        {'order': 3, 'title': 'Encore', 'duration': 159},
        ...
    ],
}

答案 1 :(得分:0)

关于您的问题,由于我无法直接关注您的代码,因此您缺少城市模型,但是我可以参考一个示例来完成您需要的事情,

注意:作为一名软件工程师,我喜欢使用体系结构,并且我对分层开发方法进行了深入的研究,因此我将就层级回答它。

serializer = SerializerNameGoesHere(AllFilteredObjectsfromModel, many=True)

将使用序列化器m2m。 这是分层方法的一个例子!

据我所知,这是解决方案

models.py

class Member(models.Model):
    member_id = models.AutoField(primary_key=True)
    member_name = models.CharField(max_length = 

class Group(models.Model):
    group_id = models.AutoField(primary_key=True)
    group_name = models.CharField(max_length = 20)
    fk_member_id = models.ForeignKey('Member', models.DO_NOTHING, 
                             db_column='fk_member_id', blank=True, null=True)

class Membership(models.Model):
    membershipid = models.AutoField(primary_key=True)
    fk_group_id = models.ForeignKey('Group', models.DO_NOTHING, 
                             db_column='fk_member_id', blank=True, null=True)
    join_date = models.DateTimeField()

serializers.py

import serializer

class AllSerializer(serializer.Serializer):
    group_id = serializer.IntegerField()
    group_name = serializer.CharField(max_length = 20)
    join_date = serializer.DateTimeField()

CustomModels.py

imports...

    class AllDataModel():
        group_id = ""
        group_name = ""
        join_date = ""

BusinessLogic.py

imports ....
class getdata(memberid):
    alldataDict = {}
    dto = []
    Member = models.Members.objects.get(member_id=memberid) #or use filter for Name
    alldataDict["MemberId"] = Member.member_id
    alldataDict["MemberName"] = Member.member_name
    Groups = models.Group.objects.filter(fk_member_id=Member)
    for item in Groups:
        Custommodel = CustomModels.AllDataModel()
        Custommodel.group_id = item.group_id
        Custommodel.group_name = item.group_name
        Membership = models.Membership.objects.get(fk_group_id=item.group_id)
        Custommodel.join_date = Membership.join_date
        dto.append(Custommodel)
    serializer = AllSerializer(dto,many=True)
    alldataDict.update(serializer.data)
    return alldataDict

现在您可以做的是:

#Member = models.Members.objects.get(member_id=memberid)
Member = models.Members.objects.filter(member_id=memberid)
#And then Loop over it
for item in Member:
   #The Rest of the code would go here!