Django-eav (แพคเกจเดิมไม่ได้ถูก mantained อีกต่อไป แต่มีส้อมที่เจริญรุ่งเรืองบางส่วน)
วิธีการแก้ปัญหานี้ขึ้นอยู่กับรูปแบบข้อมูลค่าเอนทิตีของเอนทิตีซึ่งจะใช้หลายตารางในการจัดเก็บคุณลักษณะแบบไดนามิกของวัตถุ ส่วนที่ดีเกี่ยวกับโซลูชันนี้คือ:
- ใช้แบบจำลอง Django ที่บริสุทธิ์และเรียบง่ายหลายแบบเพื่อเป็นตัวแทนเขตข้อมูลแบบไดนามิกซึ่งทำให้ง่ายต่อการเข้าใจและไม่เชื่อเรื่องฐานข้อมูล
ช่วยให้คุณสามารถแนบ / แยกการจัดเก็บแอตทริบิวต์แบบไดนามิกกับรุ่น Django ได้อย่างมีประสิทธิภาพด้วยคำสั่งง่ายๆเช่น:
eav.unregister(Encounter)
eav.register(Patient)
ทำงานร่วมกับผู้ดูแลระบบ Django อย่างดี ;
ในขณะเดียวกันก็มีพลังจริงๆ
ข้อเสีย:
- ไม่ค่อยมีประสิทธิภาพ นี่เป็นคำวิจารณ์เพิ่มเติมของรูปแบบ EAV ซึ่งต้องการรวมข้อมูลจากรูปแบบคอลัมน์เข้ากับชุดของคู่คีย์ - ค่าในแบบจำลองด้วยตนเอง
- บำรุงรักษายาก การรักษาความถูกต้องของข้อมูลจำเป็นต้องมีข้อ จำกัด คีย์ที่ไม่ซ้ำกันหลายคอลัมน์ซึ่งอาจไม่มีประสิทธิภาพในฐานข้อมูลบางตัว
- คุณจะต้องเลือกหนึ่งในส้อมเนื่องจากแพ็คเกจอย่างเป็นทางการจะไม่ได้รับการบำรุงรักษาอีกต่อไปและไม่มีผู้นำที่ชัดเจน
การใช้งานค่อนข้างตรงไปตรงมา:
import eav
from app.models import Patient, Encounter
eav.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)
เขตข้อมูล Hstore, JSON หรือ JSONB ใน PostgreSQL
PostgreSQL รองรับประเภทข้อมูลที่ซับซ้อนมากขึ้น ส่วนใหญ่ได้รับการสนับสนุนผ่านแพ็คเกจของบุคคลที่สาม แต่ในช่วงไม่กี่ปีที่ผ่านมา Django ได้นำไปใช้กับ django.contrib.postgres.fields
HStoreField :
Django-hstoreเดิมเป็นแพ็คเกจของบุคคลที่สาม แต่ Django 1.8 ได้เพิ่มHStoreFieldในตัวพร้อมกับ PostgreSQL ที่รองรับประเภทฟิลด์อื่น ๆ
วิธีนี้เป็นวิธีที่ดีที่ช่วยให้คุณมีทั้งโลกที่ดีที่สุด: ฟิลด์แบบไดนามิกและฐานข้อมูลเชิงสัมพันธ์ อย่างไรก็ตาม hstore นั้นไม่เหมาะกับประสิทธิภาพการทำงานโดยเฉพาะอย่างยิ่งถ้าคุณกำลังจะจบลงด้วยการจัดเก็บรายการหลายพันรายการไว้ในสาขาเดียว นอกจากนี้ยังรองรับสตริงสำหรับค่าเท่านั้น
#app/models.py
from django.contrib.postgres.fields import HStoreField
class Something(models.Model):
name = models.CharField(max_length=32)
data = models.HStoreField(db_index=True)
ในเปลือกของ Django คุณสามารถใช้มันได้:
>>> 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:
# equivalence
Something.objects.filter(data={'a': '1', 'b': '2'})
# subset by key/value mapping
Something.objects.filter(data__a='1')
# subset by list of keys
Something.objects.filter(data__has_keys=['a', 'b'])
# subset by single key
Something.objects.filter(data__has_key='a')
JSONField :
ฟิลด์ JSON / JSONB รองรับประเภทข้อมูลที่เข้ารหัสได้ JSON ไม่เพียง แต่คู่คีย์ / ค่าเท่านั้น แต่ยังมีแนวโน้มที่จะเร็วกว่าและ (สำหรับ JSONB) จะกะทัดรัดกว่า Hstore แพ็คเกจจำนวนมากใช้ฟิลด์ JSON / JSONB ซึ่งรวมถึงdjango-pgfieldsแต่ในขณะที่ Django 1.9 นั้นJSONFieldเป็นแบบในตัวโดยใช้ JSONB สำหรับการจัดเก็บ
JSONFieldคล้ายกับ HStoreField และอาจทำงานได้ดีขึ้นกับพจนานุกรมขนาดใหญ่ นอกจากนี้ยังรองรับประเภทอื่น ๆ นอกเหนือจากสตริงเช่นจำนวนเต็มบูลีนและพจนานุกรมที่ซ้อนกัน
#app/models.py
from django.contrib.postgres.fields import JSONField
class 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')
Django MongoDB
หรือการดัดแปลง NoSQL Django อื่น ๆ - กับพวกเขาคุณสามารถมีรูปแบบไดนามิกอย่างเต็มที่
ห้องสมุด NoSQL Django นั้นยอดเยี่ยม แต่โปรดจำไว้ว่าพวกเขาไม่ใช่ 100% ที่เข้ากันได้กับ Django เช่นการโยกย้ายไปยังDjango nonrelจาก Django มาตรฐานคุณจะต้องแทนที่ ManyToMany ด้วยListFieldเหนือสิ่งอื่นใด
ชำระเงินตัวอย่าง Django MongoDB นี้:
from djangotoolbox.fields import DictField
class 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
Django-mutantใช้งาน Foreign Key แบบไดนามิกและฟิลด์ m2m และได้รับแรงบันดาลใจจากโซลูชั่นที่เหลือเชื่อ แต่ค่อนข้างแฮ็คโดยWill Hardyและ Michael Hall
ทั้งหมดนี้มาจาก Django South hooks ซึ่งตามการพูดคุยของ Will Hardy ที่ DjangoCon 2011 (ดูมัน!)ยังมีประสิทธิภาพและทดสอบในการผลิต ( ซอร์สโค้ดที่เกี่ยวข้อง) )
คนแรกที่จะดำเนินการนี้เป็นไมเคิลฮอลล์ไมเคิลฮอลล์
ใช่นี่คือความมหัศจรรย์ด้วยวิธีการเหล่านี้คุณสามารถใช้แอป Django แบบไดนามิกและฟิลด์ด้วยฐานข้อมูลเชิงสัมพันธ์ แต่ราคาเท่าไหร่ ความเสถียรของแอพพลิเคชั่นจะทุกข์ทรมานเมื่อใช้งานหนักหรือไม่? นี่คือคำถามที่ต้องพิจารณา คุณต้องแน่ใจว่าได้ล็อคที่เหมาะสมเพื่อให้คำขอฐานข้อมูลการเปลี่ยนแปลงพร้อมกัน
หากคุณใช้งาน Michael Halls รหัสของคุณจะเป็นดังนี้:
from dynamo import models
test_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',
)