Django'nun Meta sınıfı nasıl çalışır?


191

Ben kullanarak bir sınıfa ekstra parametreler eklemek için izin Django kullanıyorum class Meta.

class FooModel(models.Model):
    ...
    class Meta:
        ...

Python'un belgelerinde bulduğum tek şey:

class FooMetaClass(type):
    ...

class FooClass:
    __metaclass__ = FooMetaClass

Ancak bunun aynı şey olduğunu düşünmüyorum.


6
Başlık Python meta hakkında soruyor, ancak soru Django meta hakkında soruyor gibi görünüyor - hangisini soruyorsunuz?
ckhan

10
@ckhan, çok yanıltıcı olan iç içe bir sınıf "Meta" deme saçma kararı (IMO) yüzünden kafası karışmıştı; yeni başlayanlara, Python'un metasınıflarına ve daha önce hiç görmemiş daha deneyimli kullanıcılara, amacı hakkında (sınıf özniteliklerini veya gerçek
metasınıfları

Yanıtlar:


233

İki farklı şey hakkında bir soru soruyorsunuz:

  1. MetaDjango modellerinde iç sınıf :

    Bu sadece modele bağlı bazı seçeneklerin (meta veri) bulunduğu bir sınıf kabıdır. Kullanılabilir izinler, ilişkili veritabanı tablosu adı, modelin soyut olup olmadığı, adın tekil ve çoğul sürümleri vb.

    Kısa açıklama burada: Django belgeleri: Modeller: Meta seçenekler

    Kullanılabilir meta seçeneklerinin listesi burada: Django belgeleri: Model Meta seçenekleri

    Django'nun son sürümü için: Django belgeleri: Model Meta seçenekleri

  2. Python'da Metaclass :

    En iyi açıklama burada: Python'da metaclasses nedir?


3
Bu iki şey birbiriyle ilişkili mi? Django'nun Metaiç sınıfı Python'un yerleşik metasınıf özelliklerini kullanmanızı engelliyor mu?
nnyby

10
@nnyby: Bu iki kavram arasında ilişki yaratan iki şey vardır: birçok kullanıcının sahip olduğu isim ve karışıklık (OP'nin orijinal soruda olduğu gibi). Ortak kafa karışıklığının ele alınmasının bu konunun önemli bir avantajı olduğuna inanıyorum. Kabul etmiyor musun?
Tadeck

49

Tadeck'in yukarıdaki Django cevabına bağlı olarak, Django'da 'class Meta:' kullanımı sadece normal Python'dur.

İç sınıf, sınıf örnekleri arasında paylaşılan veriler için uygun bir ad alanıdır (bu nedenle 'meta veri' için Meta adıdır, ancak istediğiniz herhangi bir şey diyebilirsiniz). Django'da genellikle salt okunur yapılandırma öğeleri olsa da, değiştirmenizi engelleyecek hiçbir şey yoktur:

In [1]: class Foo(object):
   ...:     class Meta:
   ...:         metaVal = 1
   ...:         
In [2]: f1 = Foo()
In [3]: f2 = Foo()
In [4]: f1.Meta.metaVal
Out[4]: 1
In [5]: f2.Meta.metaVal = 2
In [6]: f1.Meta.metaVal
Out[6]: 2
In [7]: Foo.Meta.metaVal
Out[7]: 2

Bunu doğrudan Django'da da inceleyebilirsiniz:

In [1]: from django.contrib.auth.models import User
In [2]: User.Meta
Out[2]: django.contrib.auth.models.Meta
In [3]: User.Meta.__dict__
Out[3]: 
{'__doc__': None,
 '__module__': 'django.contrib.auth.models',
 'abstract': False,
 'verbose_name': <django.utils.functional.__proxy__ at 0x26a6610>,
 'verbose_name_plural': <django.utils.functional.__proxy__ at 0x26a6650>}

Bununla birlikte, Django'da , bir model oluşturulduğunda model tarafından oluşturulan _metabir Optionsnesne olan özelliği keşfetmek istemeniz daha olasıdır metaclass. Tüm Django sınıfı 'meta' bilgilerini burada bulabilirsiniz. Django'da, Metasadece _meta Optionsnesneyi oluşturma sürecine bilgi aktarmak için kullanılır .


Bu, kullanıcı tanımlı modellerde çalışmaz: >>> myapp.models import MyModel >>> MyModel.Meta Traceback (en son çağrı son olarak): <module> AttributeError'da "<console>", satır 1 dosyası: 'MyModel' yazım nesnesinin 'meta' özelliği yok
bdf

2
Örneğin alt çizgiye ihtiyacınız varMyUser.objects.get(pk=1)._meta
Paul Whipp

Doğru, ama bu Model'in sınıfının iç Meta sınıfına erişmiyor. Bu Model örneği için _meta seçeneklerine erişir ... iç Meta sınıfının kendisine erişmenin bir yolu yoktur. Benim için kullanım örneği, MyModelProxy'nin MyModel iç Meta sınıfını devralabileceği şekilde MyModel'den bir proxy MyModelProxy sınıfını alt sınıflara ayırıyordu.
bdf

Modelin 'iç Meta sınıfı' ile ne demek istediğinizi tam olarak type(MyUser.objects.get(pk=1)).Meta
anlayamıyorum

3
"sınıf örnekleri arasında paylaşılan veriler için uygun ad alanı" O satır bunu benim için yaptı.
MGP

22

Django'nun Modelsınıfı özellikle Metabir sınıf olan bir özniteliğe sahiptir. Genel bir Python olayı değil.

Python metasınıfları tamamen farklıdır.


12
Bence cevabınız yeterince açık değil - Metasınıfın nasıl çalıştığını açıklayabilir misiniz ? OP'nin özellikle bunu sorduğuna inanıyorum.
Tadeck

7

Django modelinin Metave metasınıflarının "tamamen farklı" olduğunu iddia eden cevaplar yanıltıcı cevaplardır.

Django model sınıf nesnelerinin yapımı (yani sınıf tanımının kendisini temsil eden nesne; evet, sınıflar da nesnedir) gerçekten denilen bir metasınıf tarafından kontrol edilir ModelBase, bu kodu burada görebilirsiniz:

https://github.com/django/django/blob/master/django/db/models/base.py#L61

Ve yapan şeylerden ModelBasebiri, _metaher Django modelinde doğrulama makineleri, alan ayrıntıları, mantık tasarrufu ve benzeri özellikler oluşturmaktır. Bu işlem sırasında, modelin iç Metasınıfında belirtilen şeyler bu süreç içinde okunur ve kullanılır.

Yani, evet olsa da, bir anlamda Metave metasınıflar farklı 'şeyler' olsa da, Django model yapısının mekaniği içinde yakından ilişkilidirler; birlikte nasıl çalıştıklarını anlamak, ikisine de bakış açınızı derinleştirecektir.

Bu, Django modellerinin metasınıfları nasıl kullandığını daha iyi anlamak için yararlı bir bilgi kaynağı olabilir.

https://code.djangoproject.com/wiki/DevModelCreation

Nesnelerin genel olarak nasıl çalıştığını daha iyi anlamak istiyorsanız, bu da yardımcı olabilir.

https://docs.python.org/3/reference/datamodel.html


0

İç Meta Sınıf Belgesi Django Model meta verilerinin bu belgesi, sipariş seçenekleri (sipariş verme), veritabanı tablo adı (db_table) veya insan tarafından okunabilen tekil ve çoğul adlar (ayrıntılı_adı ve ayrıntılı_adı) şeklinde olabilir. Hiçbiri gerekli değildir ve bir modele Meta sınıfı eklemek tamamen isteğe bağlıdır. https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options


0

Django'da, bir yapılandırma sınıfı görevi görür ve yapılandırma verilerini tek bir yerde tutar !!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.