2011-10-07 13 views
5

मेरे पास दस्तावेज़ ऑब्जेक्ट्स और लेबल ऑब्जेक्ट्स का एक सेट है, और मैं उन दो ऑब्जेक्ट्स को लिंक करना चाहता हूं। यह एक आम तौर पर कई रिश्ते हैं।मॉडल सहेजते समय कई से अधिक रिश्तों को कब और कैसे बनाया जाता है?

Models.py:

class Document(models.Model): 
    title = models.CharField(max_length=50, unique=True) 
    title_slug = models.SlugField(max_length=50, unique=True, editable=False) 
    labels = models.ManyToManyField('Label') 

    def save(self, *args, **kwargs): 
     self.title_slug = slugify(self.title) 
     super(Document, self).save(*args, **kwargs) 

class Label(models.Model): 
    name = models.CharField(max_length=40, unique=True) 
    slug = models.SlugField(max_length=40, unique=True, editable=False) 

    def save(self, *args, **kwargs): 
     self.slug = slugify(self.name) 
     super(Document, self).save(*args, **kwargs) 

Views.py: मैं निम्नलिखित कोड है

class DocumentForm(ModelForm): 
    class Meta: 
     model = Document 
     fields = ["title","labels"] 

def upload_document(request): 
    if request.method == 'POST': 
     form = DocumentForm(request.POST, request.FILES) 
     if form.is_valid(): 
      new_document = form.save() 
      return HttpResponseRedirect("/thanks/") 

    else: 
     form = DocumentForm() 

    return render_to_response('upload_page.html', {'form':form}, context_instance=RequestContext(request)) 

जब मैं कोई दस्तावेज़ अपलोड, यह डेटाबेस में जुड़ जाता है, फिर भी कोई लेबल नहीं किया जा रहा है दस्तावेज़ के साथ बनाया या जुड़ा हुआ है। क्या ऐसा करने के लिए मुझे दस्तावेज़ के सेव() फ़ंक्शन में स्पष्ट रूप से कुछ जोड़ने की ज़रूरत है? या कहीं कहीं.py.py फ़ाइल में? मैं कल्पना करता यह की तरह कुछ जाना चाहते हैं: यदि लेबल है कि जोड़ा जा रहा है पहले से मौजूद है

  • देखने के लिए

    • चेक ऐसा नहीं है, तो एक नया लेबल
    • ले लो दोनों वर्तमान document_id बनाने करता है और नए/मौजूदा label_id
    • document_labels तालिका (स्वचालित रूप से कई-से-अनेक संबंध के लिए बनाया)

    मुझे लगता है कि की तरह महसूस करने के लिए एक रिकॉर्ड जोड़ना बहुत मानक कार्यक्षमता कि मैं कर रहा हूँ करने के लिए का निर्माण किया जाएगा मान लिया है django में किसी भी से अधिक रिश्ते, लेकिन यह अब तक मेरे लिए काम नहीं कर रहा प्रतीत होता है। मैं यहां पहिया को फिर से शुरू करने से बचने की कोशिश कर रहा हूं। Django के लिए कुछ नया।

    अग्रिम धन्यवाद!

  • +0

    आप एक फ़ॉर्म का उपयोग करके कर रहे हैं? क्या आप अन्य साधनों से 'दस्तावेज' जोड़ रहे हैं? आप किस बारे में बात कर रहे हैं() विधि? 'दस्तावेज़', 'लेबल' या एक रूप में से एक? ऑब्जेक्ट को सहेजने वाले कुछ नमूना दृश्य/फॉर्म/अन्य कोड प्रदान करें। – andreaspelme

    +0

    मुझे लगता है कि मुझे सच में यकीन नहीं है कि कौन सी सहेजने की विधि में जाना चाहिए। इसलिए मेरा प्रश्न =] दस्तावेजों को साइट पर किसी फॉर्म के माध्यम से जोड़ा जा रहा है। मैंने विचारों को उस प्रश्न को अद्यतन करने के लिए देखा है जो.py.py –

    उत्तर

    4

    जैसा कि अन्य लोगों ने कहा था, आप एक-शॉट दस्तावेज़ ऑब्जेक्ट और इसके कई टन क्षेत्र में सहेज नहीं सकते हैं, क्योंकि django "intermediatary join table" बनाते हैं, जिसे दस्तावेज़ ऑब्जेक्ट की आईडी की आवश्यकता होती है, जिसे उस बिंदु पर परिभाषित नहीं किया गया है।

    ModelForm में एक save_m2m समारोह नहीं है, कि the doc

    हालांकि में वर्णित है, फार्म से ही कहा जा माना जाता है, अगर यह काम नहीं करता है, हो सकता है एक चाल को ध्यान में रखते save_m2m कॉल करने के लिए है समारोह, इस तरह:

    def upload_document(request): 
        if request.method == 'POST': 
         form = DocumentForm(request.POST, request.FILES) 
         if form.is_valid(): 
          new_document = form.save() 
          form.save_m2m() 
          return HttpResponseRedirect("/thanks/") 
    
        else: 
         form = DocumentForm() 
    
        return render_to_response('upload_page.html', {'form':form}, context_instance=RequestContext(request)) 
    

    आशा है कि यह मदद करता है, स्टीफन

    +0

    अहह को सहेजने के बाद इसे सहेज लें, मुझे समस्या मिली। मेरे उदाहरण में कोड को सरल बनाने के लिए, मैंने लाइन 'new_document = form.save (प्रतिबद्ध = गलत)' ली। मुझे प्रतिबद्ध = गलत का उपयोग करना पड़ा क्योंकि मैं इसे डेटाबेस ऑब्जेक्ट पर सहेजने से पहले दस्तावेज़ ऑब्जेक्ट पर कुछ और काम कर रहा हूं, लेकिन मुझे नहीं लगता था कि एम 2 एम बचत को प्रभावित करेगा। Https://docs.djangoproject.com/en/1.3/topics/forms/modelforms/#the-save-method के लिए आपका लिंक सिर्फ वही था जो मुझे चाहिए, धन्यवाद! –

    2

    मैं सुझाव देता हूं कि Django Admin app इस तरह की स्थितियों में कैसे काम करता है। आमतौर पर, यह एक दो चरण ऑपरेशन होगा; सबसे पहले आप कई लेबल बनाएंगे, फिर आप एक दस्तावेज़ बनायेंगे, एक बहु-चयन सूची से जुड़े लेबल चुनें, फिर इसे सहेजें। Django स्वचालित रूप से दस्तावेज़ों और लेबल के बीच कई से अधिक तालिका के माध्यम से सूची में चयनित लेबल को स्वचालित रूप से संबद्ध करेगा।

    यदि आप इसे एक ही चरण में करने की उम्मीद कर रहे हैं, तो inline formsets का उपयोग करने की संभावना है। व्यवस्थापक ऐप इन्हें मुख्य रूप से विदेशी कुंजी (उदाहरण के लिए पोल और प्रश्न) के लिए उपयोग करता है, लेकिन इन्हें कई से अधिक रिश्तों के साथ सीमित डिग्री तक भी उपयोग किया जा सकता है।

    चेतावनी दी जानी चाहिए, इनलाइन फॉर्मेट मुश्किल हो सकते हैं। यदि आप ऑपरेशन को दो अलग-अलग विचारों में विभाजित कर सकते हैं, तो यह बहुत आसान होगा। दस्तावेज़ बनाने के लिए केवल लेबल बनाने के लिए एक दृश्य बनाएं और दस्तावेज़ के साथ कौन से लेबल संबद्ध करना है, यह चुनने के लिए स्वचालित रूप से एक सूची होगी।

    0

    लिंक की गई वस्तुओं को स्वचालित रूप से सहेजने पर नहीं बनाया जाता है()। आपको लेबल के लिए एक और फॉर्म बनाना चाहिए, और उन्हें स्पष्ट रूप से सहेजें।

    +0

    से मुझे लेबल के लिए एक और * फॉर्म * बनाना है ?? क्या इसका मतलब है "लेबल" फ़ील्ड को "दस्तावेज़" फ़ॉर्म से हटा देना और फिर उन्हें एक ही समय में सहेजना? –

    +0

    हां, "दस्तावेज़" फ़ॉर्म से "लेबल" फ़ील्ड को हटाएं, नया "लेबल" फ़ॉर्म बनाएं और दस्तावेज़ –

    2

    दस्तावेज़ मॉडल में आपके लेबल एक एम 2 एम फ़ील्ड है, इसलिए यह प्रस्तुत किए गए फॉर्म में बहु-चयन को प्रस्तुत करने वाला होगा (सिस्टम में उपलब्ध सभी लेबल दिखा रहा है)।

    यह मानते हुए कि तुम क्या चाहते हो,

    में views.py

    def upload_document(request): 
        if request.method == 'POST': 
         form = DocumentForm(request.POST, request.FILES) 
         if form.is_valid(): 
          labels = request.POST.getlist('labels') 
          new_document = form.save() 
          for label_id in labels: # we're only going to add currently defined labels 
           label = Label.objects.get(id=int(label_id)) 
           new_document.labels.add(label) 
          new_document.save() 
          return HttpResponseRedirect("/thanks/") 
        else: 
         form = DocumentForm() 
    
        return render_to_response('doc_form.html', {'form':form}, context_instance=RequestContext(request)) 
    

    मैं मॉडल में लेबल के लिए मॉडल अपडेट किया गया।py,

    class Label(models.Model): 
        name = models.CharField(max_length=40, unique=True) 
        slug = models.SlugField(max_length=40, unique=True, editable=False) 
    
        def save(self, *args, **kwargs): 
         self.slug = slugify(self.name) 
         super(Label, self).save(*args, **kwargs) 
    
        def __unicode__(self): 
         return self.name 
    

    आप उपयोगकर्ता भी मक्खी पर लेबल बनाने के होने के बारे में सोच रहे थे, तो आप कुछ और, एक इनपुट फ़ील्ड की तरह के साथ अपने रूप में लेबल क्षेत्र ओवरराइड करने के लिए की जरूरत है। एक उदाहरण के रूप में, आप कॉमा से अलग किए लेबल दर्ज करने के लिए उपयोगकर्ताओं को निर्देश रहे हैं, तो आप एक नवीनीकृत views.py की तरह होगा,

    for label in labels: # labels entered by user 
        try: 
         lbl = Label.objects.get(name='label') 
        except Label.DoesNotExist: 
         lbl = None 
    
        if not lbl: 
         lbl = Label() 
         lbl.name = label 
         lbl.save() 
    
        newDoc.labels.add(lbl) 
    
    newDoc.save() 
    

    आशा यह आपकी समस्या का हल या आप से काम करने के लिए कुछ देना।

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