Django में मॉडल के क्षेत्र प्राप्त करें


121

एक Django मॉडल को देखते हुए, मैं इसके सभी क्षेत्रों को सूचीबद्ध करने की कोशिश कर रहा हूं। मैंने _meta मॉडल विशेषता का उपयोग करके ऐसा करने के कुछ उदाहरण देखे हैं, लेकिन क्या मेटा के सामने अंडरस्कोर यह नहीं दर्शाता है कि _meta विशेषता एक निजी विशेषता है और इसे सीधे एक्सेस नहीं किया जाना चाहिए? ... क्योंकि, उदाहरण के लिए, _meta का लेआउट भविष्य में बदल सकता है और स्थिर एपीआई नहीं हो सकता है?

क्या _meta इस नियम का अपवाद नहीं है? क्या यह स्थिर और उपयोग करने के लिए तैयार है या इसे उपयोग करने के लिए इसे बुरा अभ्यास माना जाता है? या कोई फ़ंक्शन या किसी अन्य तरीके से _meta विशेषता का उपयोग किए बिना एक मॉडल के क्षेत्रों का आत्मनिरीक्षण करना है? नीचे कुछ लिंक की एक सूची दी गई है, जिसमें दिखाया गया है कि _meta विशेषता का उपयोग करके यह कैसे करें

किसी भी सलाह की बहुत प्रशंसा की जाएगी।

django ऑब्जेक्ट / फ़ील्ड सेट करें

http://www.djangofoo.com/80/get-list-model-fields

कैसे django मॉडल क्षेत्रों आत्मनिरीक्षण करने के लिए?


जवाबों:


144

_metaनिजी है, लेकिन यह अपेक्षाकृत स्थिर है। इसे औपचारिक रूप देने, इसे प्रलेखित करने और अंडरस्कोर को हटाने के प्रयास हैं, जो 1.3 या 1.4 से पहले हो सकते हैं। मुझे लगता है कि यह सुनिश्चित करने के लिए प्रयास किया जाएगा कि चीजें पीछे की ओर संगत हैं, क्योंकि बहुत सारे लोग वैसे भी इसका उपयोग कर रहे हैं।

यदि आप विशेष रूप से संगतता के बारे में चिंतित हैं, तो एक फ़ंक्शन लिखें जो एक मॉडल लेता है और फ़ील्ड लौटाता है। इसका मतलब है कि अगर भविष्य में कुछ बदलता है, तो आपको केवल एक फ़ंक्शन बदलना होगा।

def get_model_fields(model):
    return model._meta.fields

मेरा मानना ​​है कि यह Fieldवस्तुओं की सूची लौटाएगा । उदाहरण के लिए, प्रत्येक क्षेत्र का मान प्राप्त करने के लिए उपयोग करें getattr(instance, field.name)

अपडेट: Django योगदानकर्ताओं ने Google समर कोड के भाग के रूप में _Meta ऑब्जेक्ट को बदलने के लिए API पर काम कर रहे हैं। देखें:
- https://groups.google.com/forum/# ​​.topic
/ django - developers/ hD4roZq0wyk - https://code.djangoproject.com/wiki/new_meta_api


45
आपको इस तथ्य से भी अवगत होना चाहिए, कि यदि आपको कई-से-कई फ़ील्ड की आवश्यकता है, तो आपको एक्सेस करने की आवश्यकता है model._meta.many_to_many!
बर्नहार्ड वालेंट

1
थैंक यू विल। यह जानकर अच्छा लगा कि अन्य लोग भी _मेटा का उपयोग कर रहे हैं। मुझे एक रैपर फंक्शन होने का विचार पसंद है। आलस्य, धन्यवाद भी। यह जानने के लिए अच्छा है कि कई_to_many फ़ील्ड प्राप्त करने के लिए एक अच्छी विधि है। जो
जो जे

3
django/core/management/commands/loaddata.pyऐप्स, मॉडल और फ़ील्ड के ट्री को चलने के लिए _meta का उपयोग करता है। अनुसरण करने के लिए अच्छा पैटर्न ... और आप इसे "आधिकारिक तरीका" मान सकते हैं।
२३:२३

2
आप सामान्य विदेशी कुंजी का उपयोग कर रहे हैं, तो आप भी जांच होनी चाहिए_meta.virtual_fields
andrei1089


97

मुझे पता है कि यह पोस्ट बहुत पुरानी है, लेकिन मुझे बस किसी को भी यह बताने की परवाह है कि यह एक ही चीज़ के लिए खोज है कि ऐसा करने के लिए एक सार्वजनिक और आधिकारिक एपीआई है: get_fields()औरget_field()

उपयोग:

fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')

https://docs.djangoproject.com/en/1.8/ref/models/meta/


6
यह वास्तव में django के नए संस्करण के लिए सही उत्तर है।
छांटीलाल


3
एक प्रश्न: अगर ये "सार्वजनिक और आधिकारिक" हैं, तो वे अभी भी क्यों चल रहे हैं _meta?
क्रुबो

9

अब विशेष विधि है - get_fields ()

    >>> from django.contrib.auth.models import User
    >>> User._meta.get_fields()

यह दो मापदंडों को स्वीकार करता है जिनका उपयोग यह नियंत्रित करने के लिए किया जा सकता है कि कौन से क्षेत्र वापस आ गए हैं:

  • include_parents

    डिफ़ॉल्ट रूप से सही है। पुन: मूल रूप से मूल वर्गों पर परिभाषित फ़ील्ड शामिल हैं। यदि गलत पर सेट किया जाता है, तो get_fields () केवल वर्तमान मॉडल पर सीधे घोषित किए गए फ़ील्ड खोजेगा। ऐसे मॉडल के क्षेत्र जो सीधे तौर पर अमूर्त मॉडल या प्रॉक्सी कक्षाओं से प्राप्त होते हैं, उन्हें स्थानीय माना जाता है, अभिभावक पर नहीं।

  • include_hidden

    डिफ़ॉल्ट रूप से गलत। यदि यह सही पर सेट है, तो get_fields () में अन्य फ़ील्ड की कार्यक्षमता को वापस करने के लिए उपयोग किए जाने वाले फ़ील्ड शामिल होंगे। इसमें कोई भी फ़ील्ड शामिल होगा जिसमें एक संबंधित_नाम (जैसे कि ManyToManyField, या ForeignKey) जो "+" के साथ शुरू होता है


9

get_fields()रिटर्न ए tupleऔर प्रत्येक तत्व एक Model fieldप्रकार है, जिसे सीधे स्ट्रिंग के रूप में उपयोग नहीं किया जा सकता है। तो, field.nameफ़ील्ड नाम वापस कर देगा

my_model_fields = [field.name for field in MyModel._meta.get_fields()]
उपरोक्त कोड सभी क्षेत्रों के नाम उदाहरण के लिए एक सूची लौटाएगा


In [11]: from django.contrib.auth.models import User

In [12]: User._meta.get_fields()
Out[12]: 
(<ManyToOneRel: admin.logentry>,
 <django.db.models.fields.AutoField: id>,
 <django.db.models.fields.CharField: password>,
 <django.db.models.fields.DateTimeField: last_login>,
 <django.db.models.fields.BooleanField: is_superuser>,
 <django.db.models.fields.CharField: username>,
 <django.db.models.fields.CharField: first_name>,
 <django.db.models.fields.CharField: last_name>,
 <django.db.models.fields.EmailField: email>,
 <django.db.models.fields.BooleanField: is_staff>,
 <django.db.models.fields.BooleanField: is_active>,
 <django.db.models.fields.DateTimeField: date_joined>,
 <django.db.models.fields.related.ManyToManyField: groups>,
 <django.db.models.fields.related.ManyToManyField: user_permissions>)

In [13]: [field.name for field in User._meta.get_fields()]
Out[13]: 
['logentry',
 'id',
 'password',
 'last_login',
 'is_superuser',
 'username',
 'first_name',
 'last_name',
 'email',
 'is_staff',
 'is_active',
 'date_joined',
 'groups',
 'user_permissions']

बहुत बढ़िया जवाब! धन्यवाद!
Tms91

8

यह कुछ ऐसा है जो एक मॉडल से एक फॉर्म का निर्माण करते समय खुद Django द्वारा किया जाता है। यह _meta विशेषता का उपयोग कर रहा है, लेकिन जैसा कि बर्नहार्ड ने उल्लेख किया है, यह _meta.fields और _meta.many_to_many दोनों का उपयोग करता है। Django.forms.models.fields_for_model को देखते हुए, यह है कि आप इसे कैसे कर सकते हैं:

opts = model._meta
for f in sorted(opts.fields + opts.many_to_many):
    print '%s: %s' % (f.name, f)

4

_Meta द्वारा शामिल मॉडल फ़ील्ड संबंधित फ़ील्ड ऑब्जेक्ट की सूची के रूप में कई स्थानों में सूचीबद्ध हैं। यह एक शब्दकोश के रूप में उनके साथ काम करना आसान हो सकता है जहां चाबियाँ क्षेत्र के नाम हैं।

मेरी राय में, यह मॉडल क्षेत्र की वस्तुओं को इकट्ठा करने और व्यवस्थित करने के लिए सबसे अधिक अतार्किक और अभिव्यंजक तरीका है:

def get_model_fields(model):
  fields = {}
  options = model._meta
  for field in sorted(options.concrete_fields + options.many_to_many + options.virtual_fields):
    fields[field.name] = field
  return fields

( यह उदाहरण django.forms.models.fields_for_model में देखें।)


2
आप अपने कोड के साथ यह क्या कर रहे हैं का एक संक्षिप्त विवरण के साथ चाहते हो सकता है।
बास वैन डीजेक

2

इसके बारे में क्या खयाल है।

fields = Model._meta.fields

1
मैं कल्पना करता हूं कि कोई व्यक्ति किसी क्षेत्र के गुणों को एक्सेस करना चाहता है। इसके अलावा, जैसा कि पिछले उत्तरों में बताया गया है, हैं many_to_manyऔर virtual_fields
जॉक

@ आप सही हैं। किसी अन्य विशेषता तक पहुँचने के लिए आवश्यकता उत्पन्न हो सकती है। उत्तर संपादित किया गया।
JDE876

2

Django प्रलेखन 2.2 के अनुसार आप उपयोग कर सकते हैं:

सभी फ़ील्ड प्राप्त करने के लिए: Model._meta.get_fields()

एक व्यक्तिगत क्षेत्र प्राप्त करने के लिए: Model._meta.get_field('field name')

पूर्व। Session._meta.get_field('expire_date')


1

यदि आपको अपनी व्यवस्थापक साइट के लिए इसकी आवश्यकता है , तो एक ModelAdmin.get_fieldsविधि ( डॉक्स ) भी है, जो listफ़ील्ड नाम का एक रिटर्न देता है strings

उदाहरण के लिए:

class MyModelAdmin(admin.ModelAdmin):
    # extending change_view, just as an example
    def change_view(self, request, object_id=None, form_url='', extra_context=None):
        # get the model field names
        field_names = self.get_fields(request)
        # use the field names
        ...

0

एक और तरीका है मॉडल में फ़ंक्शन जोड़ना और जब आप उस दिनांक को ओवरराइड करना चाहते हैं जिसे आप फ़ंक्शन कह सकते हैं।

class MyModel(models.Model):
    name = models.CharField(max_length=256)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    def set_created_date(self, created_date):
        field = self._meta.get_field('created')
        field.auto_now_add = False
        self.created = created_date

    def set_modified_date(self, modified_date):
        field = self._meta.get_field('modified')
        field.auto_now = False
        self.modified = modified_date

my_model = MyModel(name='test')
my_model.set_modified_date(new_date)
my_model.set_created_date(new_date)
my_model.save()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.