2016-11-24 29 views
0

我想爲用戶提供基於現有發佈創建新發布的可能性。要做到這一點,我希望他們點擊一個鏈接到「基礎視圖」,其中包含他們希望新項目的基礎上的出版物的ID。包含n:n關係有兩個表單集。Django - 通過預先填寫表單和相應的內聯窗體集創建基於另一個對象的新對象

這應該打開一個預填充的表單與所有字段的prefield與來自出版物的數據基於。一旦用戶根據需要進行了更改,它應該爲該字段集保存新的出版物和新關係 - 後者是其中的難題。

所以我的問題是 - 我怎樣才能從數據庫中加載所有相應的表單集,然後刪除所有的PK,但仍然保持與出版物的關係?

現在就是這個樣子的get方法:

 self.object = None 
     try: 
      self.object = KombiPublikation.objects.get(pk=self.kwargs['pk']) 
     except ObjectDoesNotExist: 
      raise Http404("Keinen Output unter dieser PubID gefunden.") 

     form = KombiPublikationForm(instance=self.object) 
     pubspr_formset = KombiPublikationSpracheFormset(instance=self.object) 
     pubpers_formset = KombiPublikationPersonFormset(instance=self.object) 

但是,最終是公正現有出版物的編輯。我以某種方式必須刪除後 pk 我填充了formset或找到一種方式來填充formset不同。有任何想法嗎?

非常感謝!

這裏完整的代碼摘錄:

class PublikationBasedView(PublikationCreateView): 
    def get(self, request, *args, **kwargs): 
     self.object = None 
     try: 
      self.object = KombiPublikation.objects.get(pk=self.kwargs['pk']) 
     except ObjectDoesNotExist: 
      raise Http404("Keinen Output unter dieser PubID gefunden.") 

     #todo: delete the pk of all objects in forms in formset, else they stay the same and are also changed!! 
     #fix: delete pk in objekt in order to save it as a new objekt - else based does not work at all! 

     #self.object.pk=None 

     form = KombiPublikationForm(instance=self.object) 
     pubspr_formset = KombiPublikationSpracheFormset(instance=self.object) 
     pubpers_formset = KombiPublikationPersonFormset(instance=self.object) 



     return self.render_to_response(
      self.get_context_data(
       form=form, 
       pubspr_formset=pubspr_formset, 
       pubpers_formset=pubpers_formset, 
      ) 
     ) 

#its based on this create view 
class PublikationCreateView(LoginRequiredMixin, ShowNumberOfItems, CreateView): 
    form_class = KombiPublikationForm 
    template_name = 'output/pub_create.html' 
    model = KombiPublikation 

    def get(self, request, *args, **kwargs): 
     self.object = None 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     pubspr_formset = KombiPublikationSpracheFormset() 
     pubpers_formset = KombiPublikationPersonFormset() 

     return self.render_to_response(
      self.get_context_data(
       form=form, 
       pubspr_formset=pubspr_formset, 
       pubpers_formset=pubpers_formset 
      ) 
     ) 

    def post(self, request, *args, **kwargs): 
     self.object = None 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     pubspr_formset = KombiPublikationSpracheFormset(self.request.POST) 
     pubpers_formset = KombiPublikationPersonFormset(self.request.POST) 

     if form.is_valid() and pubspr_formset.is_valid() and pubpers_formset.is_valid(): 
      return self.form_valid(form, pubspr_formset, pubpers_formset) 
     else: 
      return self.form_invalid(form, pubspr_formset, pubpers_formset) 

    def get_success_msg(self): 
     return 'Ihr Output wurde erfolgreich unter PubID {} angelegt. Speicherort: {}. <br>'.format(self.object.pk, self.object.status) 

    def form_valid(self, form, pubspr_formset, pubpers_formset): 
     """ Called if all forms are valid.""" 
     self.object = form.save() 
     pubspr_formset.instance = self.object 
     pubspr_formset.save() 
     pubpers_formset.instance = self.object 
     pubpers_formset.save() 

     messages.success(self.request, self.get_success_msg()) 
     return redirect(self.get_success_url()) 

    def form_invalid(self, form, pubspr_formset, pubpers_formset): 
     """ Called if whether a form is invalid. Re-renders data-filled forms and errors.""" 


     return self.render_to_response(
         self.get_context_data(
           form=form, 
           pubspr_formset=pubspr_formset, 
           pubpers_formset=pubpers_formset, 

         )) 

回答

0

我解決了這個問題,因爲它是比較複雜一點,然後期望,我在這裏分享我的發現 - 如果有人發現一個簡單的解決方案隨意添加其他評論

也就是說在考慮到最終get方法:

def get(self, request, *args, **kwargs): 
    self.object = None 
    try: 
     self.object = KombiPublikation.objects.get(pk=self.kwargs['pk']) 
    except ObjectDoesNotExist: 
     raise Http404("Keinen Output unter dieser PubID gefunden.") 

    #load all form initials and render the form correctly - but save new objects 
    #1. make sure the main publikation object is saved as a new object: 
    self.object.pk = None 
    self.object.erstellungsdatum = datetime.now() 
    form = KombiPublikationForm(instance=self.object) 

    #2. get the corresponding querysets for sprache and person: 
    pubspr = KombiPublikationSprache.objects.filter(publikation=self.kwargs['pk']) 
    pubpers = KombiPublikationPerson.objects.filter(publikation=self.kwargs['pk']) 

    #make a list of dicts out of the querysets and delete pk id and fk relations 
    pubspr_listofdicts = [] 
    for pubspr in pubspr: 
     pubspr_dict= model_to_dict(pubspr) 
     del pubspr_dict['id'] 
     del pubspr_dict['publikation'] 
     pubspr_listofdicts.append(pubspr_dict) 

    pubpers_listofdicts = [] 
    for pubpers in pubpers: 
     pubpers_dict=model_to_dict(pubpers) 
     del pubpers_dict['id'] 
     del pubpers_dict['publikation'] 
     pubpers_listofdicts.append(pubpers_dict) 

    #create new formsets with the right amount of forms (leng(obj_listofdicts) 
    KombiPublikationSpracheFormset = inlineformset_factory(KombiPublikation, 
                  KombiPublikationSprache, 
                  form=KombiPublikationSpracheForm, 
                  extra=len(pubspr_listofdicts), 
                  can_delete=True, 
                  can_order=True, 
                  min_num=1, 
                  validate_min=True) 

    KombiPublikationPersonFormset = inlineformset_factory(
     KombiPublikation, 
     KombiPublikationPerson, 
     form=KombiPublikationPersonForm, 
     extra=len(pubpers_listofdicts), 
     can_delete=True, 
     can_order=True, 
     min_num=0, 
     validate_min=True) 

    #initiate the formset with initial data: 
    pubspr_formset = KombiPublikationSpracheFormset(instance=self.object, initial=pubspr_listofdicts) 
    pubpers_formset = KombiPublikationPersonFormset(instance=self.object, initial=pubpers_listofdicts) 


    return self.render_to_response(
     self.get_context_data(
      form=form, 
      pubspr_formset=pubspr_formset, 
      pubpers_formset=pubpers_formset, 
     ) 
    ) 
0

一旦你設置它綁定到該對象的窗體的instance。所有更新將針對您傳遞的對象。

相反,你需要

使用初始運行時申報表單字段的初始值。例如,您可能需要使用當前會話的用戶名填寫用戶名字段。

再就是在django.forms.models.model_to_dict一個工具,它會給你你需要initial的字典:

返回包含數據的字典中instance適合作爲傳遞窗體的initial關鍵字參數。

所以你需要做這樣的事情:

from django.forms.models import model_to_dict 

object = # Your code here... 

# You don't want `id`. Possibly others...? 
initial_data = model_to_dict(object, exclude=['id']) 

form = YourFormClass(initial=initial_data) 

# ... 

希望幫助。

+0

那裏嗨,認爲這是正確的方式。問題在於,它不會在redered窗體中設置外鍵值。 一切都在那裏,但外鍵,即使他們在字典中作爲值。 任何想法爲什麼他們不顯示在窗體中? – teconomix

+0

嗯......這可能是你的Field是ModelChoiceFields或類似的,從model_to_dict出來的數據格式不正確。你需要試驗並調整它。 –

+0

我試圖加載fk對象,並將dict中的值替換爲相應的對象。但仍然 - 外鍵值不呈現在呈現的形式... :( – teconomix

相關問題