程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

Is there a more efficient way to handle dynamic field creation in Django REST Framework serializers?

发布于2024-10-31 21:12     阅读(676)     评论(0)     点赞(6)     收藏(0)


I am working with Django REST Framework and trying to dynamically add fields to a serializer based on data selected from the UI. Specifically, I need to add fields for each commodity associated with a KindTournamentSerializer instance. These fields should represent the quantity of each commodity.

from rest_framework import serializers

class KindTournamentSerializer(CelestialSerializer):
    voucher_id = serializers.CharField(label=_("Ration number"))
    voucher_size = serializers.CharField(label=_("Ration size"))

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # Dynamically determine commodities from the instance
        if self.instance:

            selected_fields = kwargs.get('selected_fields', [])
            if 'voucher_size' in selected_fields:
                # Get the first instance to extract commodities
                first_instance = self.instance[0] if isinstance(self.instance, TournamentSerializer) else self.instance
                commodities = first_instance.rations.all()

                # Create fields for each commodity
                for ration in commodities:
                    commodity_name = ration.name
                    sanitized_name = commodity_name.replace(" ", "_").replace("-", "_")
                    field_name = f"commodity_{sanitized_name}"
                    
                    # Add the SerializerMethodField
                    commodity_field = serializers.SerializerMethodField(label=_(commodity_name))
                    self.fields[field_name] = commodity_field

                    # Dynamically bind the method for the field
                    setattr(self, f'get_{field_name}', lambda obj, name=commodity_name: self.get_commodity_value(obj, name))

    def get_commodities_data(self, obj):
        """Aggregate quantities of commodities from the latest voucher."""
        latest_voucher = obj.latest_voucher
        commodity_data = {}

        if latest_voucher:
            commodities = latest_voucher.commodities.all()
            for commodity in commodities:
                name = commodity.name
                quantity = commodity.quantity
                if name not in commodity_data:
                    commodity_data[name] = 0
                commodity_data[name] += quantity

        return commodity_data

    def get_commodity_value(self, obj, commodity_name):
        """Retrieve the quantity of a specific commodity."""
        commodities_data = self.get_commodities_data(obj)
        return commodities_data.get(commodity_name, 0)

    def to_representation(self, obj):
        """Customize representation to include commodity quantities."""
        data = super().to_representation(obj)
        
        # Add dynamic commodity fields to the representation
        commodities_data = self.get_commodities_data(obj)
        
        for field in self.fields:
            if field.startswith("commodity_"):
                commodity_name = field.replace("commodity_", "")
                data[field] = commodities_data.get(commodity_name, 0)

        return data

One of the numerous issues with the way it is defined above is that. When we call KindTournamentSerializer._declared_fields from a CSV Exporter that uses this serializer.. The __init__ method is not trigger so those dynamic fields are not created.


解决方案


暂无回答



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:https://www.pythonheidong.com/blog/article/2040412/68b4e22f44f17f93f22d/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

6 0
收藏该文
已收藏

评论内容:(最多支持255个字符)