栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Python-Django动态模型字段

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python-Django动态模型字段

到目前为止,有四种可用的方法,其中两种需要特定的存储后端:

  1. Django-eav(原始软件包已不再使用,但有一些兴旺的fork)

此解决方案基于实体属性值数据模型,实质上,它使用多个表来存储对象的动态属性。关于此解决方案的重要之处在于:

  • 使用几个简单的纯Django模型来表示动态字段,这使它易于理解并且与数据库无关。
  • 允许你使用以下简单命令将动态属性存储有效地附加/分离到Django模型:
eav.unregister(Encounter)eav.register(Patient)
  • 与Django admin很好地集成 ;

  • 同时真正强大。

缺点:

  • 不是很有效。这更多地批评了EAV模式本身,这需要手动将数据从列格式合并到模型中的一组键值对。
  • 难以维护。维护数据完整性需要多列唯一键约束,这在某些数据库上可能效率不高。
  • 你将需要选择其中一个分支,因为不再维护官方软件包,也没有明确的领导者。
    用法非常简单:
import eavfrom app.models import Patient, Encountereav.register(Encounter)eav.register(Patient)Attribute.objects.create(name='age', datatype=Attribute.TYPE_INT)Attribute.objects.create(name='height', datatype=Attribute.TYPE_FLOAT)Attribute.objects.create(name='weight', datatype=Attribute.TYPE_FLOAT)Attribute.objects.create(name='city', datatype=Attribute.TYPE_TEXT)Attribute.objects.create(name='country', datatype=Attribute.TYPE_TEXT)self.yes = EnumValue.objects.create(value='yes')self.no = EnumValue.objects.create(value='no')self.unkown = EnumValue.objects.create(value='unkown')ynu = EnumGroup.objects.create(name='Yes / No / Unknown')ynu.enums.add(self.yes)ynu.enums.add(self.no)ynu.enums.add(self.unkown)Attribute.objects.create(name='fever', datatype=Attribute.TYPE_ENUM,      enum_group=ynu)# When you register a model within EAV,# you can access all of EAV attributes:Patient.objects.create(name='Bob', eav__age=12,     eav__fever=no, eav__city='New York',     eav__country='USA')# You can filter queries based on their EAV fields:query1 = Patient.objects.filter(Q(eav__city__contains='Y'))query2 = Q(eav__city__contains='Y') |  Q(eav__fever=no)
  1. PostgreSQL中的Hstore,JSON或JSONB字段

PostgreSQL支持几种更复杂的数据类型。大多数组件都通过第三方软件包获得支持,但近年来Django已将它们引入django.contrib.postgres.fields。

HStoreField:

Django-hstore最初是第三方软件包,但是Django 1.8将HStoreField作为内置组件以及其他几种PostgreSQL支持的字段类型添加了。

从某种意义上说,这种方法很不错,它可以让你同时兼顾两个方面:动态字段和关系数据库。但是,hstore 并不是理想的性能选择,特别是如果你最终要在一个字段中存储数千个项目时。它还仅支持值字符串。

#app/models.pyfrom django.contrib.postgres.fields import HStoreFieldclass Something(models.Model):    name = models.CharField(max_length=32)    data = models.HStoreField(db_index=True)

在Django的shell中,你可以像这样使用它:

>>> instance = Something.objects.create(      name='something',      data={'a': '1', 'b': '2'})>>> instance.data['a']'1'        >>> empty = Something.objects.create(name='empty')>>> empty.data{}>>> empty.data['a'] = '1'>>> empty.save()>>> Something.objects.get(name='something').data['a']'1'

你可以对hstore字段发出索引查询:

# equivalenceSomething.objects.filter(data={'a': '1', 'b': '2'})# subset by key/value mappingSomething.objects.filter(data__a='1')# subset by list of keysSomething.objects.filter(data__has_keys=['a', 'b'])# subset by single keySomething.objects.filter(data__has_key='a')  

JSONField:

JSON / JSONB字段支持任何JSON可编码的数据类型,不仅是键/值对,而且比Hstore更快,并且(对于JSONB)更紧凑。一些软件包实现了JSON / JSONB字段,包括django-pgfields,但是从Django 1.9开始,JSONField是使用JSONB进行存储的内置方法。 JSONField与HStoreField相似,并且在使用大字典时可能会表现更好。它还支持字符串以外的类型,例如整数,布尔值和嵌套字典。

#app/models.pyfrom django.contrib.postgres.fields import JSonFieldclass Something(models.Model):    name = models.CharField(max_length=32)    data = JSonField(db_index=True)

在外壳中创建:

>>> instance = Something.objects.create(      name='something',      data={'a': 1, 'b': 2, 'nested': {'c':3}})

索引查询与HStoreField几乎相同,除了可以嵌套。复杂索引可能需要手动创建(或脚本迁移)。

>>> Something.objects.filter(data__a=1)>>> Something.objects.filter(data__nested__c=3)>>> Something.objects.filter(data__has_key='a')
  1. Django MongoDB

或其他NoSQL Django改编版-借助它们,你可以拥有完全动态的模型。

NoSQL Django库很棒,但是请记住它们不是100%与Django兼容的,例如,要从标准Django 迁移到Django-nonrel,你将需要用ListField替换ManyToMany 。

看看这个Django MongoDB示例:

from djangotoolbox.fields import DictFieldclass Image(models.Model):    exif = DictField()...>>> image = Image.objects.create(exif=get_exif_data(...))>>> image.exif{u'camera_model' : 'Spamcams 4242', 'exposure_time' : 0.3, ...}

你甚至可以创建任何Django模型的嵌入式列表:

class Container(models.Model):    stuff = ListField(EmbeddedModelField())class FooModel(models.Model):    foo = models.IntegerField()class BarModel(models.Model):    bar = models.CharField()...>>> Container.objects.create(    stuff=[FooModel(foo=42), BarModel(bar='spam')])Django-mutant:基于syncdb和South-hooks的动态模型
  1. Django-mutant实现了完全动态的外键和m2m字段。灵感来自于Will Hardy和Michael Hall 令人难以置信但有些骇人听闻的解决方案。

所有这些都基于Django South hooks,根据Will Hardy在DjangoCon 2011上的演讲 (观看!),它仍然很健壮并已在生产中进行了测试(相关的源代码)。

首先实现这一点的是迈克尔·霍尔。

是的,这是神奇的事情,通过这些方法,你可以使用任何关系数据库后端来实现完全动态的Django应用,模型和字段。但是要花多少钱呢?大量使用会损害应用的稳定性吗?这些是要考虑的问题。你需要确保维护适当的锁定,以允许同时进行数据库更改请求。

如果你使用的是Michael Halls lib,则代码将如下所示:

from dynamo import modelstest_app, created = models.DynamicApp.objects.get_or_create(name='dynamo'         )test, created = models.DynamicModel.objects.get_or_create(       name='Test',       verbose_name='Test Model',       app=test_app    )foo, created = models.DynamicModelField.objects.get_or_create(       name = 'foo',       verbose_name = 'Foo Field',       model = test,       field_type = 'dynamiccharfield',       null = True,       blank = True,       unique = False,       help_text = 'Test field for Foo',    )bar, created = models.DynamicModelField.objects.get_or_create(       name = 'bar',       verbose_name = 'Bar Field',       model = test,       field_type = 'dynamicintegerfield',       null = True,       blank = True,       unique = False,       help_text = 'Test field for Bar',    )


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/441728.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号