2010-01-08 8 views
9

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

यह करने के लिए सबसे स्पष्ट समाधान प्राथमिक कुंजी क्षेत्र लेने के लिए और डेटाबेस से मॉडल की प्रतिलिपि प्राप्त करने के लिए है:

class MyModel(models.Model): 

    def save(self, force_insert=False, force_update=False, using=None): 
     if self.id is not None: 
      unsaved_copy = MyModel.objects.get(id=self.id) 
      # Do your comparisons here 
     super(MyModel, self).save(force_insert, force_update, using) 

कि पूरी तरह से ठीक काम करता है, हालांकि, इसके बारे में हर उदाहरण के लिए डेटाबेस हिट जिस मॉडल को आप सहेज रहे हैं (यदि आप ऐसी कई बचत कर रहे हैं तो काफी असुविधाजनक हो सकता है)।

यह स्पष्ट है कि यदि कोई मॉडल उदाहरण के जीवनकाल (__init__) की शुरुआत में पुराने फ़ील्ड मानों को "याद" कर सकता है, तो डेटाबेस से मॉडल की एक प्रति पुनर्प्राप्त करने की आवश्यकता नहीं होनी चाहिए। इसलिए मैं इस छोटे से हैक के साथ आया था:

class MyModel(models.Model): 

    def __init__(self, *args, **kwargs): 
     super(MyModel, self).__init__(*args, **kwargs) 
     self.unsaved = {} 
     for field in self._meta.fields: 
      self.unsaved[field.name] = getattr(self, field.name, None) 

    def save(self, force_insert=False, force_update=False, using=None): 
     for name, value in self.unsaved.iteritems(): 
      print "Field:%s Old:%s New:%s" % (name, value, getattr(self, name, None)) 
     # old values can be accessed through the self.unsaved member 
     super(MyModel, self).save(force_insert, force_update, using) 

यह काम करने लगता है, लेकिन यह django.db.models.Model की गैर सरकारी इंटरफ़ेस का उपयोग करता है।

शायद कोई ऐसा करने के लिए एक क्लीनर तरीका जानता है?

उत्तर

2

मुझे लगता है कि आपका समाधान उचित दिखता है।

वैकल्पिक रूप से आपके पास get_and_copy() (या कुछ) नामक एक प्रबंधक विधि हो सकती है जो मूल वस्तु की एक प्रति वापस लौटाई गई है। फिर आप किसी अन्य प्रबंधक विधि का उपयोग कर सकते हैं, save_and_check() जिसने प्रतिलिपि मूल का लाभ उठाया।

FWIW: यदि आप contrib/admin टेम्पलेट्स के साथ खेल रहे हैं तो एक संदर्भ चर है जिसे original कहा जाता है जो मूल वस्तु की एक प्रति है।

अद्यतन: मैंने व्यवस्थापक क्या कर रहा है पर अधिक बारीकी से देखा। class ModelAdmin (django/contrib/admin/options.py में स्थित) में construct_change_message() नामक एक विधि है। इसे formset.changed_data और formset.changed_objects द्वारा संचालित किया जा रहा है, इसलिए django/form/models.py class BaseModelFormSet वह क्रिया है जहां कार्रवाई है। विधि save_existing_objects() देखें। विधि _existing_object() पर भी देखें। इससे पहले कि मैंने पहले उल्लेख किया है उससे थोड़ा अधिक जटिल है क्योंकि वे कई ऑब्जेक्ट्स की संभावना से निपट रहे हैं, लेकिन वे मूल रूप से पहली पहुंच पर क्वेरी सेट के परिणामों को कैश कर रहे हैं।

+0

नहीं, मैं इसे व्यवस्थापक टेम्पलेट के संदर्भ में नहीं पूछ रहा था, हालांकि मैं जांचता हूं कि यह कैसे किया गया है, टिप के लिए धन्यवाद। – shylent

0

यह फिक्स्चर के लिए काम नहीं करेगा। loaddata कमांड models.Model.base_save का उपयोग करता है। शायद सबसे साफ तरीका फ़ील्ड के लिए वर्णनकर्ताओं का उपयोग करना होगा, लेकिन किसी को यह पता लगाना होगा कि उन्हें सही ढंग से कैसे व्यवस्थित किया जाए।

संबंधित मुद्दे