Django Rest框架&实体属性值模型(EAV)数据模型 [英] Django Rest Framework & Entity–attribute–value model (EAV) Data Model

查看:290
本文介绍了Django Rest框架&实体属性值模型(EAV)数据模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自django.db导入模型的

  

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

class Entity(models.Model):

实体的EAV

entity = models.CharField(max_length = 216 ,
null = False,default ='entity_name',
name ='entity',verbose_name ='实体的EAV',
db_index = True,
unique = True



class资产(models.Model):

EAV
的资产
asset = models.CharField(max_length = 216,null = False,
default ='asset',name ='asset',
verbose_name ='EAV资产'

entity = models.ForeignKey(to = Entity)

class Meta:
unique_一起=(资产,实体)


类值(models.Model):

EAV
的值
value = models.CharField(max_length = 216,
null = False,default ='value',
name ='value',verbose_name ='EAV的价值'

asset = models.ForeignKey(to = Asset)
owner = models.ForeignKey(User,verbose_name ='EAV Owner',related_name ='eav')

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

序列化器

 类EntitySerializer(serializers.Serializer):
id = serializers.IntegerField(label ='ID',read_only = True)
entity = serializers.CharField(label =EAV的实体,max_length = 216,required = False)


class AssetSerializer(serializers.Ser ializer):
id = serializers.IntegerField(label ='ID',read_only = True)
asset = serializers.CharField(default ='asset',label ='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 ='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)

期望的序列化 / p>

  {
entities:[
{
实体:英雄,
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
}
]
},
{
实体:英雄,
id:1,
owner {
name:SuperMan,
id:2
},
groups:[
{
id :1,
name:SuperHeroes Group
}
],
资产:[
{
:Name,
value:SuperMan,
asset_id: 1,
value_id:3
},
{
资产:年龄,
值:30,
asset_id:1,
value_id:4
}
]
},
{
实体:Villian,
id:1,
owner:{
name:Joker,
id:3
},
group:[
{
id:2,
name:SuperVillians Group
}
],
资产:[
{
asset:Name,
value:Joker,
asset_id:3,
value_id :4
},
{
资产:年龄,
值:30,
asset_id:4,
value_id:5
}
]
},
{
实体:人,
id:1,
owner:{
name:Puny Human,
i d:3
},
groups:[
{
id:2,
name
}
],
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 人,
资产:{
id:1,
资产:名称,
实体:{
:1,
entity:Human
}
},
owner:{
id:1,
用户名:Puny人
}
},
{
id:2,
value:26,
asset b $ bid:2,
资产:年龄,
实体:{
id:1,
entity
}
},
owner:{
id:1,
username:PunyHuman
}
$,
{
id:3,
value:26,
asset:{
id:3,
资产:年龄,
实体:{
id:2,
实体:英雄
}
},
owner:{
id:2,
username:BatMan
}
},
{
id:4,
value:BatMan,
asset:{
id:3,
asset ,
entity:{
id:2,
entity:Hero
}
},
owner {
id:2,
username:BatMan
}
},
{
id:5,
value :26,
资产:{
id:3,
资产:年龄,
实体:{
id:2,
entity:Hero
}
},
owner:{
id:3,
username:SuperMan
}
},
{
id:6,
value:SuperMan,
资产:{
id:4,
资产:名称,
实体:{
id:2,
实体:Hero
}
},
owner:{
id:3,
username:SuperMan
}
}
]
}

查看

  class EntityAssetValueAPIView(APIView):

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

#如果要使用pk以外的对象查找,请设置'lookup_field'。
#对于更复杂的查找需求,覆盖`get_object()`。
lookup_field ='pk'
#lookup_url_kwarg =无

#用于查询过滤的过滤器后端类
#filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

#用于查询分页的风格。
#pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
#def allowed_methods(self):
#http_method_names = ['get','post','put','patch','delete'头,'选项','追踪']
#返回http_method_names
def get(self,request,* args,** kwargs):
eav = self.queryset.all()
serializer = self.serializer_class(eav,many = True)
返回响应(serializer.data)

我想做的是获取分配给USER的所有ENTITIES(连同ASSET& VALUES)。



相同的数据是向用户发送一个新的ENTITY ASSIGNMENT。



从我从DRF了解到的内容,我需要一个API视图,API视图会调用serializer,所以我必须创建一个自定义Serializer,然后保存数据我必须覆盖创建方法,其中我将有这些单独的序列化程序来验证数据并保存它。



我无法发送所需的响应或者收到REQUEST进入。



什么应该是一种方式?

解决方案

我已经面临类似的问题,所以我将在这里解释一下。



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

  class Asset(models.Model):

资产EAV

asset = models.CharField(max_length = 216,null = False ,
default ='asset',name ='asset',
verbose_name ='EAV的资产'

entity = models.ForeignKey(to = Entity,related_name ='

class Value(models.Model):

EAV
的值$
value = models.CharField( max_length = 216,
null = False,default ='value',
name ='value',verbose_name ='EAV的价值'

asset = models.ForeignKey( to = Asset,related_name ='asset_value')
owner = models.ForeignKey(User,verbose_name ='EAV Owner',related_name ='eav )

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

  queryset = Entity.objects.filter('** condition come here **')
.values('id' ,'实体','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.Seri alizer):

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

$ / code code code code code code code code code code code code < $ c>并且从该对象我们可以获得 owner_id ,因为我们最初已经获取了相关数据。



所以这里的主要意图是最初获取所有数据,然后根据您的要求将该数据进行系列化。



现有的嵌套服务不支持您所需的响应格式。



不te:初始查询重要,您可能需要使用与之相关的预取,因为我们使用反向关系获取数据。此外,我没有测试查询器,所以必须确保正确的相关名称用于获取相关数据。


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')

Serializers

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)

Expected Serialization

{
  "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
        }
      ]
    }
  ]
}

Achieved Serialization

{
  "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 View

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)

What I want to do is, Get all the ENTITIES Assigned to a USER ( along with the ASSET & VALUES ).

The same data is posted for a NEW ENTITY ASSIGNMENT to USER .

From What I understood from DRF, I would need an API view, API view would call serializer, so, I would have to create a custom Serializer, then to save the data I have to override create method, where in I will have these separate serializers that would validate the data and save it.

I am not able to send the desired RESPONSE or ingest the REQUEST coming in.

What should be a way forward ?

解决方案

I have faced the similar problem So I'll explain a little scenario here. So you can take reference from that.

Added some related names in models :

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')

initial queryset looks like this, the idea is to fetch all information that is required initially:

 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',)

Pass this queryset when trying to make response :

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

Same process goes for groups and asset fields.

in get_owner() we have entity object and from that object we can get owner_id , as we have already fetched related data initially.

So the main idea here to fetch all data initially and then serilaize that data according to your requirement.

Existing Nested Serailization do not support the response format you required.

Note : Initial querset is vry important , you may need to use prefetch related there because we are fetching data using reverse relationship. Also I didn't test the queryset so have to make sure that correct related_names are used to fetch related data.

这篇关于Django Rest框架&amp;实体属性值模型(EAV)数据模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆