सभी संबंधित Django मॉडल ऑब्जेक्ट्स प्राप्त करें


88

मैं उन सभी मॉडल वस्तुओं की सूची कैसे प्राप्त कर सकता हूं जिनके पास किसी ऑब्जेक्ट को इंगित करने वाला एक फॉरेनके है? (DELETE CASCADE से पहले Django एडमिन में डिलीट कन्फर्मेशन पेज जैसा कुछ)।

मैं डेटाबेस में डुप्लिकेट ऑब्जेक्ट्स को मर्ज करने के एक सामान्य तरीके के साथ आने की कोशिश कर रहा हूं। मूल रूप से मैं उन सभी वस्तुओं को चाहता हूं जिनके पास फॉरेनकेयर्स पॉइंट्स हैं जो ऑब्जेक्ट "बी" पर ऑब्जेक्ट "ए" को इंगित करने के लिए अपडेट किया जाएगा ताकि मैं तब कुछ महत्वपूर्ण खोए बिना "बी" को हटा सकूं।

आपकी सहायताके लिए धन्यवाद!


1
यह Django स्निपेट निश्चित रूप से जांचने लायक है!
निक मेरिल

मैं खुद उसी चीज को लागू करने की कोशिश कर रहा हूं। क्या आप अपना समाधान साझा करने के लिए तैयार हैं? निस्संदेह setसंबंधित वस्तु ए की ओर कैसे संकेत करती है?
यूजीन

जवाबों:


84

Django <= 1.7

यह आपको सभी संबंधित वस्तुओं के लिए संपत्ति के नाम देता है:

links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]

आप सभी संबंधित वस्तुओं को प्राप्त करने के लिए कुछ इस तरह का उपयोग कर सकते हैं:

for link in links:
    objects = getattr(a, link).all()
    for object in objects:
        # do something with related object instance

मैंने यह पता लगाने के लिए कुछ समय बिताया ताकि मैं अपने एक मॉडल पर एक तरह का "ऑब्जर्वर पैटर्न" लागू कर सकूं। आशा है कि यह उपयोगी है।

Django 1.8+

उपयोग करें _meta.get_fields(): https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields ( _get_fields()स्रोत में भी उलटा देखें )


7
all()भाग एक पर असफल हो जायेगी OneToOneField। आपको किसी तरह इसका पता लगाना होगा।
अगस्त

2
यह ManyToMany कनेक्शन नहीं दिखाता है और पदावनत किया गया था। Django में 1.8+ इसके साथ प्रतिस्थापित करने की अनुशंसा की जाती है _meta.get_fields(): docs.djangoproject.com/en/1.10/ref/models/meta/... (देखें reverseमें _get_fields()स्रोत भी)
int_ua

1
@Int_ua के संपादन के लिए धन्यवाद! मुझे आश्चर्य है कि जब तक यह काम किया तब तक यह समाधान Django के साथ संगत रहा।
लूट

4
इसे जारी रखते हुए _meta.get_fields(): टिप, यह मेरे लिए समाधान का हिस्सा था links = [field.get_accessor_name() for field in obj._meta.get_fields() if issubclass(type(field), ForeignObjectRel)](दी from django.db.models.fields.related import ForeignObjectRel)
driftcatcher

20

@digitalPBK करीब था ... यहाँ शायद आप Django के निर्मित सामान का उपयोग करने के लिए देख रहे हैं जो Django व्यवस्थापक में उपयोग किया जाता है हटाने के दौरान संबंधित वस्तुओं को प्रदर्शित करने के लिए

from django.contrib.admin.utils import NestedObjects
collector = NestedObjects(using="default") #database name
collector.collect([objective]) #list of objects. single one won't do
print(collector.data)

यह आपको Django व्यवस्थापन को प्रदर्शित करने की अनुमति देता है - संबंधित वस्तुओं को हटाया जाना।


FWICT यह काफी सही ढंग से काम नहीं करता है। यह उन रिश्तों का पालन करने के लिए प्रकट होता है जो विलोपन के मापदंड का अर्थ नहीं करते हैं, हालांकि मुझे यकीन नहीं है कि क्यों।
१२:२० बजे कैटस्कुल

1
क्या यह मेरा है, या क्या Collector(लाइन 1 पर आयात किया गया) का उपयोग नहीं किया गया है?
djvg

7

इसे आजमाइए।

class A(models.Model):
    def get_foreign_fields(self):
      return [getattr(self, f.name) for f in self._meta.fields if type(f) == models.fields.related.ForeignKey]


6

निम्नलिखित वह है जो सभी संबंधित वस्तुओं को प्राप्त करने के लिए django का उपयोग करता है

from django.db.models.deletion import Collector
collector = Collector(using="default")
collector.collect([a])

print collector.data

1
झरना प्रतीत नहीं होता है। पूर्ण अंतर जानने के लिए इस पार्टिकलर एक के आसपास पर्याप्त परीक्षण नहीं किया है, लेकिन कैस्केडिंग के लिए मेरा उत्तर देखें।
IMFletcher

6

links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]

आप सभी संबंधित वस्तुओं को प्राप्त करने के लिए कुछ इस तरह का उपयोग कर सकते हैं:

for link in links:
    objects = getattr(a, link.name).all()
    for object in objects:
        # do something with related object instance

Django के 1.10 आधिकारिक डॉक्स से:

MyModel._meta.get_all_related_objects () बन जाता है:

[
    f for f in MyModel._meta.get_fields()
    if (f.one_to_many or f.one_to_one)
    and f.auto_created and not f.concrete
]

इसलिए अनुमोदित उदाहरण लेकर हम इसका उपयोग करेंगे:

links = [
            f for f in MyModel._meta.get_fields()
            if (f.one_to_many or f.one_to_one)
            and f.auto_created and not f.concrete
        ]

for link in links:
    objects = getattr(a, link.name).all()
    for object in objects:
        # do something with related object instance

बस अपने उत्तर को थोड़ा सा सही करने के लिए python for link in links: objects = getattr(a, link.name).all() for object in objects:
नाम नागो

5
for link in links:
    objects = getattr(a, link).all()

संबंधित सेटों के लिए काम करता है, लेकिन विदेशियों के लिए नहीं। चूंकि संबंधित प्रबंधक गतिशील रूप से बनाए गए हैं, इसलिए कक्षा के नाम को आइंस्टीन करना आसान है ()

objOrMgr = getattr(a, link)
 if objOrMgr.__class__.__name__ ==  'RelatedManager':
      objects = objOrMgr.all()
 else:
      objects = [ objOrMgr ]
 for object in objects:
      # Do Stuff

4

Django 1.9
get_all_related_objects () को हटा दिया गया है

#Example: 
user = User.objects.get(id=1)
print(user._meta.get_fields())

नोट: हटाए गए InDjango110110 चेतावनी: 'get_all_related_objects एक अनौपचारिक एपीआई है जिसे हटा दिया गया है। आप इसे 'get_fields ()' से बदल सकते हैं


get_fields संबंधित ऑब्जेक्ट्स को वापस नहीं करता है।
इयानिटक

यह Django 1.8 पर भी रिवर्स कनेक्शन लौटाता है
int_ua

2

संबंधित मॉडल में फ़ील्ड (केवल नाम) की सूची प्राप्त करने का एक और तरीका है।

def get_related_model_fields(model):
    fields=[]
    related_models = model._meta.get_all_related_objects()
    for r in related_models:
        fields.extend(r.opts.get_all_field_names())
    return fields

2

दुर्भाग्य से, user._meta.get_fields () केवल उपयोगकर्ता से सुलभ संबंधों को लौटाता है, हालांकि, आपके पास कुछ संबंधित वस्तु हो सकती है, जो संबंधित_नाम = '+' का उपयोग करती है। ऐसे मामले में, संबंध उपयोगकर्ता द्वारा वापस नहीं किया जाएगा। _meta.get_fields ()। इसलिए, यदि आपको वस्तुओं को मर्ज करने के लिए सामान्य और मजबूत तरीके की आवश्यकता है, तो मैं ऊपर उल्लिखित कलेक्टर का उपयोग करने का सुझाव दूंगा।

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