डेटाबेस से पुनः लोड करें django ऑब्जेक्ट


160

क्या डेटाबेस से django ऑब्जेक्ट की स्थिति को ताज़ा करना संभव है? मेरा मतलब है कि व्यवहार के बराबर:

new_self = self.__class__.objects.get(pk=self.pk)
for each field of the record:
    setattr(self, field, getattr(new_self, field))

अद्यतन: ट्रैकर में एक फिर से खोलने / wontfix युद्ध मिला: http://code.djangoproject.com/ticket -901 । अभी भी समझ में नहीं आता है कि अनुरक्षकों को यह पसंद क्यों नहीं है।


एक साधारण SQL संदर्भ में, इसका कोई मतलब नहीं है। डेटाबेस ऑब्जेक्ट केवल आपके लेन-देन के खत्म होने के बाद बदला जा सकता है और ए commmit। एक बार जब आप ऐसा कर लेते हैं, तो आपको अगले एसक्यूएल लेनदेन के लिए इंतजार करना होगा। ऐसा क्यों करते हैं? अगले लेनदेन के लिए आप कितने समय तक इंतजार करेंगे?
S.Lott

यह एक अनावश्यक कार्य की तरह लगता है; डेटाबेस से ऑब्जेक्ट को फिर से देखने के लिए पहले से ही संभव है।
Stephan

मैं भी इसे पसंद करूंगा, लेकिन इसे यहां
eruciform

2
यह उचित नहीं है क्योंकि Django मॉडल ऑब्जेक्ट समीप हैं। यदि आपको एक ही तालिका पंक्ति दो वस्तुओं में मिलती है - X1 = X.objects.get (id = 1); x2 = X.objects.get (id = 1), वे समान के रूप में परीक्षण करेंगे लेकिन वे अलग-अलग वस्तुएं हैं और राज्य साझा नहीं है। आप दोनों को स्वतंत्र रूप से बदल सकते हैं और उन्हें बचा सकते हैं - अंतिम बचाया डेटाबेस में पंक्ति की स्थिति निर्धारित करता है। इसलिए सरल असाइनमेंट - X1 = X.objects.get (id = 1) के साथ पुनः लोड करना सही है। पुनः लोड विधि होने से कई लोग गलत तरीके से उस X.f = 'नए मूल्य' का संदर्भ ले सकते हैं; (X1.f == x2.f) सत्य है।
पॉल व्हिप

जवाबों:


259

Django 1.8 ताज़ा वस्तुओं के रूप में बनाया गया है। डॉक्स से लिंक करें

def test_update_result(self):
    obj = MyModel.objects.create(val=1)
    MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
    # At this point obj.val is still 1, but the value in the database
    # was updated to 2. The object's updated value needs to be reloaded
    # from the database.
    obj.refresh_from_db()
    self.assertEqual(obj.val, 2)

@ fcracker79 हाँ, यह केवल 1.8 में लागू किया गया था। Django के पुराने संस्करणों के लिए आप अन्य उत्तरों में से एक के साथ सबसे अच्छा जा रहे हैं।
टिम फ्लेचर

1
डॉक्स साधनों में वर्णित "सभी गैर-आस्थगित क्षेत्र अपडेट किए गए हैं" क्या निश्चित नहीं है?
युंति

1
@Yunti आप कर सकते हैं स्थगित क्षेत्रों, या स्पष्ट रूप से के लिए पूछने के केवल एक सबसेट क्षेत्रों के और जिसके परिणामस्वरूप वस्तु केवल आंशिक रूप से भरे जाएंगे। refresh_from_dbकेवल ऐसे पहले से ही आबादी वाले क्षेत्रों को अपडेट करेगा।
301_Moved_Permanently

डॉक्स में विवरण नहीं मिल सका, लेकिन DoesNotExistकॉल करते समय अंतर्निहित ऑब्जेक्ट हटा दिए जाने पर यह ठीक से अपवाद को फेंक देता है refresh_from_db। FYI करें।
टिम टिस्डाल

28

मैंने डेटाबेस से ऑब्जेक्ट को पुनः लोड करना अपेक्षाकृत आसान पाया है जैसे:

x = X.objects.get(id=x.id)

19
हां, लेकिन ... उसके बाद आपको इस ऑब्जेक्ट के सभी संदर्भों को अपडेट करना होगा। बहुत काम और त्रुटि-प्रवण नहीं।
grep

2
यह आवश्यक पाया गया जब अजवाइन ने django के बाहर db में मेरी वस्तु को अपडेट किया, django ने स्पष्ट रूप से ऑब्जेक्ट का एक कैश रखा क्योंकि इसमें कोई विचार नहीं था कि यह बदल गया था।
बॉब स्प्रीं

3
django.db.models.loading आयात get_model से; उदाहरण = get_model (उदाहरण) .objects.get (pk = inst.pk)
Erik

1
@grep ने इस उपयोग के मामले के लिए एक परीक्षण लिखने में केवल 2 घंटे खो दिए: 1: एक मॉडल को आरम्भ करें; 2: फॉर्म के माध्यम से मॉडल को अपडेट करें; 3: परीक्षण करें कि नया मान अपडेट किया गया है .... तो हाँ, त्रुटि प्रवण।
vlad-ardelean

3
मुझे लगता है कि refresh_from_dbइन सभी समस्याओं को हल करता है।
फ्लिम

16

@ Grep की टिप्पणी के संदर्भ में, क्या ऐसा करना संभव नहीं होना चाहिए:

# Put this on your base model (or monkey patch it onto django's Model if that's your thing)
def reload(self):
    new_self = self.__class__.objects.get(pk=self.pk)
    # You may want to clear out the old dict first or perform a selective merge
    self.__dict__.update(new_self.__dict__)

# Use it like this
bar.foo = foo
assert bar.foo.pk is None
foo.save()
foo.reload()
assert bar.foo is foo and bar.foo.pk is not None

समाधान के लिए धन्यवाद। यदि केवल SO ने कई अप-वोट की अनुमति दी है!
user590028

11
Django अब refresh_from_dbविधि प्रदान करता है।
फ्लिम

9

जैसा कि @ फ्लीम ने बताया, यह वास्तव में बहुत बढ़िया समाधान है:

foo.refresh_from_db()

यह डेटाबेस से ऑब्जेक्ट के सभी डेटा को पुनः लोड करता है।

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