Django: स्ट्रिंग से मॉडल प्राप्त करें?


133

Django में, आप जैसे रिश्ते निर्दिष्ट कर सकते हैं:

author = ForeignKey('Person')

और फिर आंतरिक रूप से इसे स्ट्रिंग "व्यक्ति" को मॉडल में बदलना होगा Person

यह कार्य कहां से होता है? मैं इसका उपयोग करना चाहता हूं, लेकिन मैं इसे नहीं ढूंढ सकता।

जवाबों:


167

Django 3.0 के रूप में, यह है AppConfig.get_model(model_name, require_ready=True)

Django 1.9 विधि के रूप में है django.apps.AppConfig.get_model(model_name)
- दानीहप

Django 1.7 के रूप में django.db.models.loadingनए एप्लिकेशन लोडिंग सिस्टम के पक्ष में पदावनत (1.9 में हटाया जाना) है।
- स्कॉट वुडल


मिल गया। यह यहाँ परिभाषित किया गया है:

from django.db.models.loading import get_model

के रूप में परिभाषित किया गया है:

def get_model(self, app_label, model_name, seed_cache=True):

11
यह समाधान Django 1.7 में पदावनत किया गया है, इस समाधान के लिए अन्य उत्तर देखें: stackoverflow.com/a/26126935/155987
टिम सेलर

4
हाय @mpen, मैं आपको अपना उत्तर अपडेट करने का सुझाव देता हूं। Django पर 1.9 get_model को AppConfig पर परिभाषित किया गया है :from django.apps import AppConfig
dani herrera

1
django.apps.AppConfig एक जनरेटर प्रकार है जो मॉडल ऑब्जेक्ट की तरह काम नहीं कर सकता है।
नीरज कुमार

2
Django 1.7+ में Django ऐप रजिस्ट्री पर get_model () का उपयोग करना बेहतर है, जो इसके माध्यम से उपलब्ध है django.apps.apps.get_model(model_name)। AppConfig ऑब्जेक्ट एक अलग उद्देश्य के लिए अभिप्रेत है, और आपको कॉल करने के लिए AppConfig उदाहरण बनाने की आवश्यकता है get_model()
zlovelady

2
Django 1.11 के जवाब की जरूरत है @luke_aus द्वारा प्रदान
जॉर्ज Zimmer

132

django.db.models.loadingनए एप्लिकेशन लोडिंग सिस्टम के पक्ष में Django 1.7 ( 1.9 में हटा दिया गया ) में पदावनत किया गया था ।

Django 1.7 डॉक्स हमें इसके बजाय निम्नलिखित देते हैं:

>>> from django.apps import apps
>>> User = apps.get_model(app_label='auth', model_name='User')
>>> print(User)
<class 'django.contrib.auth.models.User'>

मैंने pydoc के "find" फंक्शन का उपयोग किया ... यहाँ अंतर के बारे में सुनिश्चित नहीं है, लेकिन Django के भीतर रहने के लिए मैंने इस पद्धति पर स्विच किया है। धन्यवाद।
वोरथ-कोडर

61

बस किसी के लिए अटक जाना (जैसे मैंने किया):

from django.apps import apps

model = apps.get_model('app_name', 'model_name')

app_nameउद्धरणों का उपयोग करके सूचीबद्ध किया जाना चाहिए, जैसा कि होना चाहिए model_name(अर्थात इसे आयात करने का प्रयास न करें)

get_model लोअर केस या अपर केस 'मॉडल_नाम' स्वीकार करता है


32

अधिकांश मॉडल "तार" "appname.modelname" के रूप में दिखाई देते हैं ताकि आप get_model पर इस भिन्नता का उपयोग करना चाहें

from django.db.models.loading import get_model

your_model = get_model ( *your_string.split('.',1) )

Django कोड का वह भाग जो आमतौर पर इस तरह के तारों को एक मॉडल में बदल देता है, यह इससे थोड़ा अधिक जटिल है django/db/models/fields/related.py:

    try:
        app_label, model_name = relation.split(".")
    except ValueError:
        # If we can't split, assume a model in current app
        app_label = cls._meta.app_label
        model_name = relation
    except AttributeError:
        # If it doesn't have a split it's actually a model class
        app_label = relation._meta.app_label
        model_name = relation._meta.object_name

# Try to look up the related model, and if it's already loaded resolve the
# string right away. If get_model returns None, it means that the related
# model isn't loaded yet, so we need to pend the relation until the class
# is prepared.
model = get_model(app_label, model_name,
                  seed_cache=False, only_installed=False)

मेरे लिए, यह कोर कोड में एकल फ़ंक्शन में इसे विभाजित करने के लिए एक अच्छा मामला प्रतीत होता है। हालाँकि, यदि आप जानते हैं कि आपके तार "App.Model" प्रारूप में हैं, तो ऊपर दिए गए दो लाइनर काम करेंगे।


3
मुझे लगता है कि दूसरी पंक्ति होनी चाहिए your_model = get_model(*your_string.rsplit('.', 1)):। ऐप लेबल कभी-कभी बिंदीदार प्रारूप होता है, हालांकि मॉडल का नाम हमेशा एक मान्य पहचानकर्ता होता है।
रॉकलाईट

1
ऐसा लगता है कि नए में यह आवश्यक नहीं है apps.get_model। "एक शॉर्टकट के रूप में, यह विधि फॉर्म में एकल तर्क को भी स्वीकार करती है app_label.model_name।"
रेन एवरेट

16

Django 1.7+ में ऐसा करने का धन्य तरीका है:

import django
model_cls = django.apps.apps.get_model('app_name', 'model_name')

इसलिए, सभी रूपरेखा ट्यूटोरियल के विहित उदाहरण में:

import django
entry_cls = django.apps.apps.get_model('blog', 'entry')  # Case insensitive

9

यदि आपको पता नहीं है कि आपका मॉडल किस ऐप में मौजूद है, तो आप इसे इस तरह से खोज सकते हैं:

from django.contrib.contenttypes.models import ContentType 
ct = ContentType.objects.get(model='your_model_name') 
model = ct.model_class()

याद रखें कि आपका_मॉडल_नाम लोअरकेस होना चाहिए।


4

मुझे यकीन नहीं है कि यह Django में कहाँ किया गया है, लेकिन आप ऐसा कर सकते हैं।

प्रतिबिंब के माध्यम से स्ट्रिंग को वर्ग नाम मैपिंग।

classes = [Person,Child,Parent]
def find_class(name):
 for clls in classes:
  if clls.__class__.__name__ == name:
   return clls

1
क्या यह क्लस्टर है ।__ क्लास __.__ name__ या सिर्फ क्लल्स ।__ name__?
विनायक कालियारक्कल २५'१ani

4

आलसी के लिए कम कोड के साथ एक और प्रतिपादन। Django 2+ में परीक्षण किया गया

from django.apps import apps
model = apps.get_model("appname.ModelName") # e.g "accounts.User"

1

यहाँ स्ट्रिंग से एक वर्ग प्राप्त करने के लिए एक कम django- विशिष्ट दृष्टिकोण है:

mymodels = ['ModelA', 'ModelB']
model_list = __import__('<appname>.models', fromlist=mymodels)
model_a = getattr(model_list, 'ModelA')

या आप यहां दिखाए गए अनुसार importlib का उपयोग कर सकते हैं :

import importlib
myapp_models = importlib.import_module('<appname>.models')
model_a = getattr(myapp_models, 'ModelA')

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.