2017-01-11 17 views
12

स्थिति

Django प्रॉक्सी मॉडल


हम जो कार्यक्षमता के विभिन्न प्रकार के लिए एक टिकट समर्थन प्रणाली से टिकट का उपयोग कुछ अलग एप्लिकेशन नहीं है।

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

एक एप्लिकेशन टिकट समर्थन प्रणाली में टिकटों के लिए हमारे ग्राहक डेटाबेस से ग्राहकों को लिंक करता है। पहले इस प्रणाली में हमारे टिकट समर्थन प्रणाली के अंदर टिकटों का अपना प्रतिनिधित्व था, kayakodb द्वारा प्रदान की गई एपीआई का उपयोग करके टिकटों के लिए पूछताछ। इसके बाद ग्राहकों और डोमेन को जोड़ने के लिए टिकटों के इस प्रतिनिधित्व का उपयोग किया गया। हालांकि यह बहुत जटिल था और बहुत तार्किक नहीं था। इसलिए हमने इसे प्रॉक्सी मॉडल पर स्विच करने और उन मॉडलों को स्थानांतरित करने का विकल्प चुना जो ग्राहकों और डोमेन के लिंक का प्रतिनिधित्व kayakodb पर करते हैं। आइए इस एप्लिकेशन को sidebar पर कॉल करें।

एक और नया एप्लिकेशन कॉल के साथ एक स्पष्ट अवलोकन में टिकट समर्थन प्रणाली से टिकट दिखाता है, इसलिए हमारा समर्थन विभाग आसानी से देख सकता है कि कौन से कॉल और टिकट ग्राहक से संबंधित हैं। इस प्रणाली में sidebar के प्रॉक्सी मॉडल के लिए प्रॉक्सी मॉडल है, क्योंकि sidebar मॉडल द्वारा प्रदान की गई कुछ कार्यक्षमताओं को इस एप्लिकेशन के लिए कुछ अन्य प्रॉक्सी मॉडल घोषित करने के लिए भी आवश्यक है। आइए इस प्रोजेक्ट को WOW पर कॉल करें।

sidebar और WOW एप्लिकेशन एक ही प्रोजेक्ट/रिपोजिटरी का हिस्सा हैं। हम इस भंडार को Coneybeach पर कॉल करेंगे जिसका अपना डेटाबेस है। हालांकि, kayakodb एक पूरी तरह से असंबंधित परियोजना है। इसे Coneybeach में एक आवश्यकता फ़ाइल के माध्यम से शामिल किया गया है जिसे हम pip के माध्यम से स्थापित करते हैं।

समस्या


जब माइग्रेशन नए सेटअप के लिए Django स्थापित kayakodb जो निश्चित रूप से है, एक नहीं जाने के लिए एक प्रॉक्सी मॉडल माइग्रेशन द्वारा बनाए बनाने। किसी भी समय हम kayakodb का एक नया संस्करण स्थापित करेंगे, यह इस माइग्रेशन को ओवरराइट करेगा। अकेले इस तथ्य को छोड़ दें कि kayakodb इस बारे में कुछ नहीं जानना चाहिए कि कौन से मॉडल इसका उपयोग करते हैं।

कोड


kayakodb अंदर Ticket मॉडल:

class Ticket(models.Model): 
    """ 
    This model is a representation of the data stored in the "kayako" database table "swtickets". Minus a lot of stuff 
    we don't use. If you add a field make sure it has the same name as the field in kayako.swtickets. 
    """ 
    # Fields, functions and manager etc. 

    class Meta: 
     db_table = 'swtickets' 
     managed = False 

SidebarTicket प्रॉक्सी मॉडल अंदर sidebar:

from kayakodb.models import Ticket  

class SidebarTicket(Ticket): 
    class Meta: 
     # Since this class is a wrapper we don't want to create a table for it. We only want to access the original 
     # model as we always do, but provide a different interface (when it comes to functions). Proxy models allow us 
     # to do this: https://docs.djangoproject.com/en/1.10/topics/db/models/#proxy-models 
     proxy = True 

     # Don't look for this model in the sidebar tables, but in the kayakodb tables. 
     app_label = 'kayakodb' 

    # Some extra functions 

Contact वर्ग TicketWrapper (के रूप में Hynekc द्वारा अनुरोध से विरासत में मिली एर)।यह मॉडल (हालांकि नहीं मुद्दों इस मॉडल के साथ जहाँ तक मुझे पता है कर रहा हूँ कर रहे हैं) TicketWrapper के लिए बेस मॉडल और एक अन्य मॉडल कॉल प्रतिनिधित्व के रूप में प्रयोग किया जाता है:

class Contact(models.Model): 
    type = None 

    class Meta: 
     abstract = True 

    def __getattr__(self, attr): 
     if attr in ['customers', 'add_customer_id', 'remove_all_customers', 'byters', 'domainnames', 'add_domain_name', 
        'remove_domain_name', 'add_text', 'remove_text', 'texts', 'creation_date', 'add_tag', 'get_tags', 
        'remove_tag', 'identifier']: 
      raise NotImplementedError('You should implement {}'.format(attr)) 
     raise AttributeError(attr) 

TicketWrapper प्रॉक्सी मॉडल अंदर WOW:

from sidebar.models import SidebarTicket 

class TicketWrapper(Contact, SidebarTicket): 
    class Meta: 
     # Since this class is a wrapper we don't want to create a table for it. We only want to access the original 
     # model as we always do, but provide a different interface (when it comes to functions). Proxy models allow us 
     # to do this: https://docs.djangoproject.com/en/1.10/topics/db/models/#proxy-models 
     proxy = True 

     # Don't look for this model in the WOW database, but in the kayakodb database. 
     app_label = 'kayakodb' 

    # Some extra functions 

क्या मैंने कोशिश की


  • मैं वें निर्दिष्ट नहीं की कोशिश की है है प्रॉक्सी मॉडल दोनों के लिए ई app_label। यह सही माइग्रेशन बनाता है, लेकिन प्रॉक्सी मॉडल को kayakodb.Ticket मॉडल को कॉनीबीच डेटाबेस में देखने का कारण बनता है।
  • मैंने उप-वर्गों के लिए abstract = True निर्दिष्ट करने का प्रयास किया है, लेकिन यह सुनिश्चित नहीं था क्योंकि मैं अभी भी मॉडल के लिए प्रबंधक का उपयोग करने में सक्षम होना चाहता हूं।
  • मैंने माइग्रेशन को आगे बढ़ने पर विचार किया जो वर्तमान में वास्तविक kayakodb प्रोजेक्ट में बनाया गया है, लेकिन मुझे नहीं लगता कि यह एक अच्छा समाधान है। kayakodb को अपने मॉडल के कार्यान्वयन या जहां उनका उपयोग किया जाता है, उसके बारे में कुछ भी नहीं पता होना चाहिए।
  • ./manage.py check 0 अंक लौटाता है।

प्रश्न


मैं एक मॉडल है कि एक अलग डेटाबेस या प्रोजेक्ट में स्थित होता है के लिए एक प्रॉक्सी मॉडल कैसे बना सकते हैं?

संपादित


kayakodb.Ticket मॉडल की स्थापना अप्रबंधित होने के लिए बाद WOW परियोजना kayakodb में सभी मॉडल के लिए एक प्रवास को बनाने के लिए कोशिश करता है। परिणाम:

Migrations for 'sidebar': 
    0004_auto_20170116_1210.py: 
    - Delete model Ticket 

Migrations for 'kayakodb': 
    0001_initial.py: 
    - Create model Staff 
    - Create model Tag 
    - Create model Ticket 
    - Create model TicketPost 
    - Create model TicketTag 
    - Create model TicketCustomer 
    - Create model TicketDomain 
    - Create proxy model SidebarTicket 
    - Alter unique_together for ticketdomain (1 constraint(s)) 
    - Alter unique_together for ticketcustomer (1 constraint(s)) 
    - Create proxy model TicketWrapper 
+0

@ e4c5 हाँ मुझे यह पता है। यह अच्छा और सब कुछ है, लेकिन अगर यह ओवरराइट होने पर परिणाम का _is_ है। – Bono

+0

आप खुद ऐसा कहते हैं "ऐसा इसलिए है क्योंकि भविष्य में माइग्रेशन में प्रॉक्सी मॉडल शायद किसी अन्य मॉडल द्वारा संदर्भित किया जा सकता है।" अन्यथा इसे माइग्रेशन बनाने की परेशानी क्यों होगी यदि इसे बाद में फेंक दिया जा सके? – Bono

+0

तुमने मुझे वहाँ मिला !! करीबी वोट वापस लेना। – e4c5

उत्तर

4

हैं एक मौजूदा डेटाबेस, आपको अपने सभी मॉडलों के लिए managed = False सेट करने की आवश्यकता है। हालांकि, यह अभी भी गलत ऐप (kayakodb) के अंदर बनाए गए प्रॉक्सी मॉडल के माइग्रेशन की समस्या को छोड़ देता है।

hacky ठीक है कि काम हो सकता है (इस मामले में sidebar) के लिए प्रवास डाल करने के लिए जो कुछ भी एप्लिकेशन ठीक है करने के लिए प्रॉक्सी मॉडल की app_label बदल रहा है, और एक रूटर है कि इस प्रॉक्सी मॉडल इंगित करेगा बनाने पढ़ सकते हैं और से लिखने के लिए kayakodb

उदा।प्रॉक्सी मॉडल:

# in sidebar/models.py 

class SidebarTicket(KayakoTicket): 
    class Meta: 
     proxy = True 
     app_label = 'sidebar' 

और इस परियोजना के अंदर रूटर यह का उपयोग करता है:

from django.conf import settings 
from kayakodb.models import Ticket 

class ProxyDatabaseRouter(object): 
    def allow_proxy_to_different_db(self, obj_): 
     # check if this is a sidebar proxy to the Ticket model in kayakodb 
     return isinstance(obj_, Ticket) and obj_._meta.proxy and obj_._meta.app_label == 'sidebar' 

    def db_for_read(self, model, **hints): 
     if issubclass(model, Ticket) and model._meta.proxy and model._meta.app_label == 'sidebar': 
      return 'kayakodb' 
     # the rest of the method goes here 

    def db_for_write(self, model, **hints): 
     if issubclass(model, Ticket) and model._meta.proxy and model._meta.app_label == 'sidebar': 
      return 'kayakodb' 
     return None 
     # the rest of the method goes here 

    def allow_relation(self, obj1, obj2, **hints): 
     if self.allow_proxy_to_different_db(obj1) or self.allow_proxy_to_different_db(obj2): 
      return True 
     # the rest of the method goes here 
+0

यह उपयोगी है, लेकिन स्थिति 'अगर मॉडल == साइडबार टिकट:' अभी भी अमान्य है, क्योंकि साइडबार टिकट केवल प्रॉक्सी है, लेकिन डेटाबेस मॉडल को पर्याप्त रूप से वर्णित नहीं किया गया है और इसलिए सही स्थिति ज्ञात नहीं है। – hynekcer

+1

@hynekcer जैसा कि मैंने कहा, तुलना वास्तव में की जाती है, यह महत्वपूर्ण नहीं है, उपरोक्त आधे छद्म कोड पर विचार करें। पढ़ने और लिखने के लिए डीबी भी मॉडल में ही संग्रहीत किया जा सकता है, राउटर विधियों को 'गेटैटर (मॉडल, "_CUSTOM_DATABASE", कोई नहीं) वापस करने की इजाजत देता है, यदि आवश्यकता हो, जो मॉडल नहीं है क्योंकि मॉडल राउटर में पास हो जाता है तरीकों। –

+0

राउटर कोड स्निपेट को बेहतर तरीके से अपडेट किया गया है यदि क्लोज़ और 'allow_relation' विधि अनुपलब्ध थी –

4

tl; डॉ लेकिन मैं एक शब्द router जो उल्लेख नहीं है के लिए अपने प्रश्न grepped, तो मुझे लगता था के रूप में @hynekcer कहा कि अगर kayakodb है बात आप देख रहे हैं Database Routers

+0

यदि प्रश्न है "मैं किसी मॉडल या प्रोजेक्ट में स्थित मॉडल के लिए प्रॉक्सी मॉडल कैसे बना सकता हूं", तो उत्तर "डेटाबेस राउटर का उपयोग" हो सकता है। मदद करने की कोशिश करने के लिए खेद है। – yedpodtrzitko

+0

क्षमा करें कठोर होने का मतलब नहीं था। मैं क्षमाप्रार्थी हूं। विभिन्न डेटाबेस में मॉडल को लिखना समस्या नहीं है (किसी भी मामले में मेरे लिए)। समस्या यह है कि गलत स्थान पर माइग्रेशन बनाया गया है (और यदि आप सवाल पढ़ते हैं, तो आप इसे देख चुके होंगे :))। आपको बताएं कि, यदि आप डीबी राउटर के बारे में अधिक जानकारी शामिल करने के लिए अपना प्रश्न संपादित करते हैं (उदाहरण प्रदान करें)। मैं अपना डाउन वोट हटाने में सक्षम हूं। प्रश्न पर पूरी तरह से देख रहे हैं मैं सहमत हूं कि यह _could_ जवाब रहा है। – Bono

4

tl; डॉ उपयोग

class Meta: 
    managed = False 

DB में सभी मॉडलों है कि नियंत्रित नहीं किया जाना चाहिए के लिए Django द्वारा। (अर्थात kayakodb)


यह ध्यान देने योग्य है कि PyPI Kayako अन्य भाषा में लिखे कुछ कायाको ऐप के लिए अजगर एपीआई (Djago के बिना) है।

यह जानना उपयोगी है कि कयाको और वाह अलग-अलग डेटाबेस में हैं लेकिन यह एक मौलिक जानकारी नहीं है। Django अनुमति देता है उदा। कि एक मॉडल दो डेटाबेस में मौजूद है: प्राथमिक और माध्यमिक डीबी। मेटा विकल्प सबसे महत्वपूर्ण हैं, इस मामले में managed = False विकल्प। यह Integrating Django with a legacy database मामले के लिए है। इसका मतलब यह नहीं है कि केवल एक बहुत ही पुरानी परियोजना है, लेकिन एक परियोजना जो पायथन + डीजेगो में नहीं लिखी गई है या माइग्रेशन का समर्थन नहीं करती है और सूचनाओं को साझा नहीं करती है जो माइग्रेशन अभी तक लागू नहीं हैं। हो सकता है कि कयाको का एक नया संस्करण डेटाबेस में एक नया फ़ील्ड जोड़ देगा, आपको उस क्षेत्र को पढ़ने की ज़रूरत नहीं है या यदि आप इसे मॉडल में जोड़ते हैं, तो Django डेटाबेस में फ़ील्ड जोड़ने के लिए ज़िम्मेदार नहीं है क्योंकि इसे कयाको अपग्रेड द्वारा नियंत्रित किया जाता है।

आप वैकल्पिक रूप से डेटाबेस राउटर का उपयोग कयाकोडब ऐप (कहीं नहीं) के लिए कोई टेबल बनाने के लिए नहीं कर सकते हैं और कयाकोड डेटाबेस में कोई भी टेबल नहीं बना सकते हैं। Django उपयोगकर्ताओं और समूहों के लिए:

फ़ाइल myrouter.py या इसी तरह

class MyRouter(object): 
    allow_migrate(db, app_label, model_name=None, **hints): 
     if app_label == 'kayakodb' or db == 'kayakodb': 
      return False 

फ़ाइल settings.py

DATABASE_ROUTERS = ['path.to.myrouter.MyRouter',...] 
# ... if another router has been defined previously 

लाभ यह है कि यह किसी भी वर्तमान या भविष्य के लिए माइग्रेशन को अक्षम करता है मॉडल, लेकिन मैं किसी भी बाद के डेवलपर को स्पष्ट करने के लिए kayakodb/models.py में टिप्पणियों के लिए कहीं भी class Meta: managed = False टेक्स्ट जोड़ने की अनुशंसा करता हूं, क्योंकि वह कर सकता है पहले राउटर को आसानी से पढ़ना भूल जाते हैं।

आप कयाको एपीआई के न्यूनतम और अधिकतम संस्करण पर अपने प्रोजेक्ट संस्करणों की निर्भरता लिख ​​सकते हैं, लेकिन यह माइग्रेशन के रूप में नहीं हो सकता है।


आपका एक और समस्या यह है कि "A proxy model must inherit from exactly one non-abstract model class...।", लेकिन आपके प्रॉक्सी मॉडल Contact और SidebarTicket से TicketWrapper इनहेरिट करती है। यह बकवास जैसा दिखता है और मुझे आश्चर्य है कि आपको कोई त्रुटि नहीं दिखाई दे रही है TypeError: Proxy model 'TicketWrapper' has more than one non-abstract model base class. वही संपर्क अधिक टिकटों द्वारा साझा किया जा सकता है। (क्या यह पंजीकृत उपयोगकर्ता नहीं है? क्या वह मुद्दे के इतिहास के दौरान अपने उपयोगकर्ता प्रोफ़ाइल में कुछ भी नहीं बदल सकता है?) यह संभवतः एक बहु विरासत से संपर्क करने के लिए एक विदेशी कुंजी होना चाहिए।

+0

'संपर्क' इस मामले में एक अमूर्त Django मॉडल है, तो यह ठीक है। मैंने 'कयाकोडब' मॉडल के लिए 'प्रबंधित = गलत' सेट किया है। लेकिन जब मैं 'वाह' प्रोजेक्ट में माइग्रेशन बनाने का प्रयास करता हूं तो अब यह सभी 'कयाकोडब' मॉडल के लिए माइग्रेशन बनाने की कोशिश करता है (भले ही वे अप्रबंधित हैं)। राउटर को सेट करते समय 'कयाकोडब' मॉडल के लिए माइग्रेशन की अनुमति न दें, लेकिन इसका मतलब यह भी है कि प्रॉक्सी मॉडल माइग्रेशन नहीं बनाया गया है, जिसे मुझे (AFAIA) की आवश्यकता है। तो मैं अभी भी समस्या में भाग रहा हूं कि मैं कायाकोड में निर्दिष्ट मॉडल के लिए प्रॉक्सी मॉडल (या एक के लिए माइग्रेशन) नहीं बना सकता। – Bono