SORU
28 EKİM 2011, Cuma


Django dinamik model alanları

Bir iş üzerinde çalışıyorumçoklu kiracılar oturuyorformları ek veri toplamak ve verileri rapor için bazı kullanıcılar kendi veri alanları tanımlayabilirsiniz uygulama (yönetici). İkinci bit JSONField mükemmel bir seçenek yapar, yerine aşağıdaki çözümüm var:

class CustomDataField(models.Model):
    """
    Abstract specification for arbitrary data fields.
    Not used for holding data itself, but metadata about the fields.
    """
    site = models.ForeignKey(Site, default=settings.SITE_ID)
    name = models.CharField(max_length=64)

    class Meta:
        abstract = True

class CustomDataValue(models.Model):
    """
    Abstract specification for arbitrary data.
    """
    value = models.CharField(max_length=1024)

    class Meta:
        abstract = True

Site için bir ForeignKey nasıl not - her Siteye özel veri alanları farklı bir dizi olacak, ama aynı veritabanını kullanır. Daha sonra çeşitli somut veri alanları olarak tanımlanabilir:

class UserCustomDataField(CustomDataField):
    pass

class UserCustomDataValue(CustomDataValue):
    custom_field = models.ForeignKey(UserCustomDataField)
    user = models.ForeignKey(User, related_name='custom_data')

    class Meta:
        unique_together=(('user','custom_field'),)

Bu aşağıdaki kullanılmasına yol açar:

custom_field = UserCustomDataField.objects.create(name='zodiac', site=my_site) #probably created in the admin
user = User.objects.create(username='foo')
user_sign = UserCustomDataValue(custom_field=custom_field, user=user, data='Libra')
user.custom_data.add(user_sign) #actually, what does this even do?

Ama bu çok hantal, özellikle el ile ilgili veri oluşturmak ve beton modeli ile ilişkilendirmek için ihtiyacı hissediyor. Daha iyi bir yaklaşım var mı?

Önceden bunun aksine, atılan: bu seçenek

  • Özel-the-fly tabloları değiştirmek için SQL. Kısmen bu ölçek olmaz çünkü kısmen de sıradan bir yazar çünkü bu çok fazla.
  • Şema-az NoSQL gibi çözümler. Onlara karşı değilim, ama yine de uygun değiller. Sonuçta bu veriyazılı ve olasılık üçüncü taraf raporlama uygulaması kullanan var.
  • Peki sorguları ile çalışmak için gitmiyor gibi, yukarıdaki gibi, JSONField.

CEVAP
28 EKİM 2011, Cuma


Bugün itibariyle, dört mevcut yaklaşımlar, iki tanesi belirli bir depolama arka uç gerektiren vardır:

  1. Django-eav(orijinal paketi artık mantained ama bazı vardırthriving forks)

    Bu çözüm Entity Attribute Value veri modelini temel alır, birkaç tablo nesneleri için dinamik öznitelikleri depolamak için kullanır aslında. Bu çözüm konusunda büyük bir parça olduğunu:

    • saf ve basit birkaç Django modelleri bunu anlamak için basit yapar, dinamik alanları, göstermek için kullanır ve veritabanı-agnostik;
    • etkili/ayırmak dinamik öznitelik depolama gibi basit komutları ile model Django eklemek için izin verir:

      eav.unregister(Encounter)
      eav.register(Patient)
      
    • Nicely integrates with Django admin;

    • Aynı zamanda çok güçlü olmayı.

    Olumsuzlukları:

    • Çok verimli değil. Bu el modeli-anahtar değer çiftleri bir dizi için bir sütun biçimi verileri birleştirme gerektiren etkin değeri deseni kendisi, bir eleştiri daha.
    • Zor korumak için. Veri bütünlüğünü korumak bazı veritabanları üzerinde verimsiz olabilir multi-sütun benzersiz anahtar kısıtlaması gerektirir.
    • Resmi paketi artık korunur beri one of the forks, seçmek gerekir ve net bir lideri yok.

    Kullanımı oldukça basittir:

    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)
    
  2. Django-hstore django-hstore-flattenfields

    (Django-hstore paketirecent forks. Orada da aynı şekildedjango-pgfieldssadece dizi alanı sağlayan , ama ne istediğinizi muhtemelen değildir).

    Bu hstore kullanımı modülü yapan PostgreSQL bir arka uç. Bununla düzenlenebilir ve değiştirilebilir uçlu sözlük saklayan bir DictionaryField olabilir.

    Bu yaklaşım, her iki dünyanın en iyi sağlar, bu bir anlamda iyidir: dinamik alan ve ilişkisel veritabanı. Ancak, hstore özellikle eğer bir alanda binlerce ürün saklamak sona yapacaksanız 33**.

    #app/models.py
    class Something(models.Model):
        name = models.CharField(max_length=32)
        data = hstore.DictionaryField(db_index=True)
    

    Django-shell bu gibi kullanabilirsiniz:

    >>> 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 alanlar karşı endeksli sorguları verebilir:

    # equivalence
    Something.objects.filter(data={'a': '1', 'b': '2'})
    
    # subset by key/value mapping
    Something.objects.filter(data__contains={'a': '1'})
    
    # subset by list of keys
    Something.objects.filter(data__contains=['a', 'b'])
    
    # subset by single key
    Something.objects.filter(data__contains='a')    
    
  3. Django MongoDB

    Veya diğer NoSQL uyarlamalar. tamamen dinamik modeller olabilir Django.

    NoSQL Django kütüphaneler büyük, ama unutmayın, onlar 0 Django uyumlu, örneğin, göç Django-nonrel standart Django gerekir yerine ManyToMany ListField başka şeyler de.

    Bu Django MongoDB örnek ödeme:

    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, ...}
    

    Hatta herhangi bir Django modelleri embedded lists oluşturabilirsiniz:

    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')]
    )
    
  4. Django-mutant: Dynamic models based on syncdb and South-hooks

    Django-mutant tamamen dinamik bir Dış Anahtar ve m2m alanları uygular. Ve Will Hardy ve Michael Hall tarafından inanılmaz ama biraz hackish çözümler esinlenmiştir.

    Bu Django Güney kanca dayalı olan, Will Hardy's talk at DjangoCon 2011 göre(dikkat et!)yine de sağlam ve üretim (relevant source code) test edilmiştir.

    implement this ilk Michael Hall.

    Evet, bu sihirli, elde edebilirsiniz bu yaklaşımlartamamen dinamik Django uygulamalar, modeller ve alanlarherhangi bir ilişkisel veritabanı arka ucu ile. Ama ne pahasına? Uygulamanın istikrar yoğun kullanımı üzerine yaşayacaktır? Bu dikkate alınması gereken sorular bunlar. Eşzamanlı veritabanı değiştirme istekleri izin vermek için lock düzgün korumak için emin olmak gerekir.

    Eğer lib Michael Salonları kullanıyorsanız, kodunuzu bu gibi görünecektir:

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

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • audivila

    audivila

    5 HAZİRAN 2009
  • GenTechPC

    GenTechPC

    1 Temmuz 2007
  • Marques Brownlee

    Marques Brow

    21 Mart 2008