【问题标题】:Django Rest Framework & Entity–attribute–value model (EAV) Data ModelDjango Rest 框架和实体-属性-值模型 (EAV) 数据模型
【发布时间】:2016-04-20 06:50:16
【问题描述】:
from django.db import models

# django user
from django.contrib.auth.models import User

class Entity(models.Model):
    """
    Entity of EAV
    """
    entity = models.CharField(max_length=216,
                            null=False, default='entity_name',
                            name='entity', verbose_name='Entity of EAV',
                            db_index=True,
                            unique=True
                            )


class Asset(models.Model):
    """
    Asset of EAV
    """
    asset = models.CharField(max_length=216, null=False,
                            default='asset', name='asset',
                            verbose_name='Asset of EAV'
                            )
    entity = models.ForeignKey(to=Entity)

    class Meta:
        unique_together = ("asset", "entity")


class Value(models.Model):
    """
    Value of EAV
    """
    value = models.CharField(max_length=216,
                             null=False, default='value',
                             name='value', verbose_name='Value of EAV'
                             )
    asset = models.ForeignKey(to=Asset)
    owner = models.ForeignKey(User, verbose_name='EAV Owner', related_name='eav')

    class Meta:
        unique_together = ('value', 'asset', 'owner')

序列化器

class EntitySerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID', read_only=True)
    entity = serializers.CharField(label='Entity of EAV', max_length=216, required=False)


class AssetSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID', read_only=True)
    asset = serializers.CharField(default='asset', label='Asset of EAV', max_length=216)
    entity = EntitySerializer(read_only=True)


class ValueSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID', read_only=True)
    value = serializers.CharField(default='value', label='Value of EAV', max_length=216)
    asset = AssetSerializer(read_only=True)
    owner = UserModelSerializer(read_only=True)


class EntityAssetValueSerializer(serializers.Serializer):
    entity = EntitySerializer(many=True)
    asset = AssetSerializer(many=True)
    value = ValueSerializer(many=True)

预期的序列化

{
  "entities": [
    {
      "entity": "Hero",
      "id": 1,
      "owner": {
        "name": "BatMan",
        "id": "1"
      },
      "groups": [
        {
          "id": "1",
          "name": "SuperHeroes Group"
        }
      ],
      "asset": [
        {
          "asset": "Name",
          "value": "BatMan",
          "asset_id": 1,
          "value_id": 1
        },
        {
          "asset": "Age",
          "value": "30",
          "asset_id": 1,
          "value_id": 2
        }
      ]
    },
    {
      "entity": "Hero",
      "id": 1,
      "owner": {
        "name": "SuperMan",
        "id": "2"
      },
      "groups": [
        {
          "id": "1",
          "name": "SuperHeroes Group"
        }
      ],
      "asset": [
        {
          "asset": "Name",
          "value": "SuperMan",
          "asset_id": 1,
          "value_id": 3
        },
        {
          "asset": "Age",
          "value": "30",
          "asset_id": 1,
          "value_id": 4
        }
      ]
    },
    {
      "entity": "Villian",
      "id": 1,
      "owner": {
        "name": "Joker",
        "id": "3"
      },
      "groups": [
        {
          "id": "2",
          "name": "SuperVillians Group"
        }
      ],
      "asset": [
        {
          "asset": "Name",
          "value": "Joker",
          "asset_id": 3,
          "value_id": 4
        },
        {
          "asset": "Age",
          "value": "30",
          "asset_id": 4,
          "value_id": 5
        }
      ]
    },
    {
      "entity": "Person",
      "id": 1,
      "owner": {
        "name": "Puny Human",
        "id": "3"
      },
      "groups": [
        {
          "id": "2",
          "name": "Humans Group"
        }
      ],
      "asset": [
        {
          "asset": "Name",
          "value": "Human Being",
          "asset_id": 5,
          "value_id": 6
        },
        {
          "asset": "Age",
          "value": "30",
          "asset_id": 6,
          "value_id": 7
        }
      ]
    }
  ]
}

实现序列化

{
  "eav": [
    {
      "id": 1,
      "value": "Human",
      "asset": {
        "id": 1,
        "asset": "Name",
        "entity": {
          "id": 1,
          "entity": "Human"
        }
      },
      "owner": {
        "id": 1,
        "username": "PunyHuman"
      }
    },
    {
      "id": 2,
      "value": "26",
      "asset": {
        "id": 2,
        "asset": "Age",
        "entity": {
          "id": 1,
          "entity": "Human"
        }
      },
      "owner": {
        "id": 1,
        "username": "PunyHuman"
      }
    },
    {
      "id": 3,
      "value": "26",
      "asset": {
        "id": 3,
        "asset": "Age",
        "entity": {
          "id": 2,
          "entity": "Hero"
        }
      },
      "owner": {
        "id": 2,
        "username": "BatMan"
      }
    },
    {
      "id": 4,
      "value": "BatMan",
      "asset": {
        "id": 3,
        "asset": "Name",
        "entity": {
          "id": 2,
          "entity": "Hero"
        }
      },
      "owner": {
        "id": 2,
        "username": "BatMan"
      }
    },
    {
      "id": 5,
      "value": "26",
      "asset": {
        "id": 3,
        "asset": "Age",
        "entity": {
          "id": 2,
          "entity": "Hero"
        }
      },
      "owner": {
        "id": 3,
        "username": "SuperMan"
      }
    },
    {
      "id": 6,
      "value": "SuperMan",
      "asset": {
        "id": 4,
        "asset": "Name",
        "entity": {
          "id": 2,
          "entity": "Hero"
        }
      },
      "owner": {
        "id": 3,
        "username": "SuperMan"
      }
    }
  ]
}

API 视图

class EntityAssetValueAPIView(APIView):

    queryset = Value.objects.select_related('asset', 'asset__entity', 'owner')
    serializer_class = ValueSerializer

    # If you want to use object lookups other than pk, set 'lookup_field'.
    # For more complex lookup requirements override `get_object()`.
    lookup_field = 'pk'
    # lookup_url_kwarg = None

    # The filter backend classes to use for queryset filtering
    # filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

    # The style to use for queryset pagination.
    # pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
    # def allowed_methods(self):
    #     http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    #     return http_method_names
    def get(self, request, *args, **kwargs):
        eav = self.queryset.all()
        serializer = self.serializer_class(eav, many=True)
        return Response(serializer.data)

我想要做的是,将所有实体分配给一个用户(连同资产和价值)。

为 USER 的 NEW ENTITY ASSIGNMENT 发布相同的数据。

根据我对 DRF 的了解,我需要一个 API 视图,API 视图会调用序列化程序,因此,我必须创建一个自定义序列化程序,然后为了保存数据,我必须重写 create 方法,其中我将拥有这些单独的序列化程序来验证数据并保存它。

我无法发送所需的响应或接收进来的请求。

前进的方向应该是什么?

【问题讨论】:

    标签: python django serialization django-rest-framework entity-attribute-value


    【解决方案1】:

    我也遇到过类似的问题,所以我将在这里解释一个小场景。所以你可以参考一下。

    在模型中添加了一些相关名称:

    class Asset(models.Model):
        """
        Asset of EAV
        """
        asset = models.CharField(max_length=216, null=False,
                                default='asset', name='asset',
                                verbose_name='Asset of EAV'
                                )
        entity = models.ForeignKey(to=Entity, related_name='asset_entity')
    
    class Value(models.Model):
        """
        Value of EAV
        """
        value = models.CharField(max_length=216,
                                 null=False, default='value',
                                 name='value', verbose_name='Value of EAV'
                                 )
        asset = models.ForeignKey(to=Asset, related_name='asset_value')
        owner = models.ForeignKey(User, verbose_name='EAV Owner', related_name='eav')
    

    初始查询集看起来像这样,其想法是获取最初需要的所有信息:

     queryset = Entity.objects.filter('**condition comes here**')
                    .values('id', 'entity', 'asset_entity', 'asset_entity__asset', 'asset_entity__asset_value', 'asset_entity__asset_value__value',
                        'asset_entity__asset_value__owner_id',)
    

    尝试做出响应时传递此查询集:

    serializer = serializer(queryset, many=True, context={'request': request})
    

    Serailizers:

    class Owner_Serializer(serializers.ModelSerializer)
    
            class Meta:
                model = User
                exclude = ('**exclude fields you want to exclude**', )
    
    
    class EntitySerializer(serializers.Serializer):
    
            id = serializers.IntegerField(source='id')
            entity = serializers.CharField(source='entity')
            owner =  serializers.SerializerMethodField()
            groups =  serializers.SerializerMethodField()
            asset =  serializers.SerializerMethodField()
    
    
            def get_owner(self, obj):
                return Owner_Serializer(obj.get('asset_entity__asset_value__owner_id'), context=self.context).data
    

    组和资产字段也是如此。

    get_owner() 我们有 entity object 并且我们可以从该对象中获得 owner_id ,因为我们最初已经获取了相关数据。

    所以这里的主要思想是首先获取所有数据,然后根据您的要求对这些数据进行序列化。

    现有的嵌套序列化不支持您需要的响应格式。

    注意:初始查询集非常重要,您可能需要在那里使用预取相关,因为我们正在使用反向关系获取数据。此外,我没有测试查询集,因此必须确保使用正确的相关名称来获取相关数据。

    【讨论】:

      猜你喜欢
      • 2011-05-11
      • 2011-02-14
      • 2017-09-15
      • 2010-11-15
      • 2020-04-16
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 2015-10-29
      相关资源
      最近更新 更多