2016-11-24 7 views
0

既存のパブリケーションに基づいて新しいパブリケーションを作成することができます。これを行うには、新しいアイテムを基にしたいパブリケーションのIDを含む "basedview"へのリンクをクリックするようにします。 n:n関係には2つの形式があります。Django - フォームと対応するインラインフォームセットを事前に入力して別のオブジェクトに基づいて新しいオブジェクトを作成する

すべてのフィールドがprefieldされたフォームを、それが基づいているパブリケーションのデータでprefieldで開くはずです。ユーザーが必要に応じて変更を加えたら、フィールドセットの新しいパブリケーションと新しいリレーションシップを保存する必要があります。後者は難しい部分です。

私の質問は、データベースからすべての対応するフォームセットを読み込み、それらのpkをすべて削除しても、パブリケーションアイテムとの関係を維持するにはどうすればよいですか?

 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) 

しかし、それは、既存のパブリケーションのちょうど編集する終わる:

は、今のところは、GETメソッドでは、このようなものです。の後に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。すべての更新は、渡されたオブジェクトになります。

代わりに、実行時にフォームフィールドの初期値を宣言するための初期

使用する必要があります。たとえば、現在のセッションのユーザ名をユーザ名フィールドに入力するとします。

次にあなたがinitialのために必要な辞書あげるdjango.forms.models.model_to_dictのユーティリティがあります:

は、フォームのinitialキーワード引数として渡すのに適しinstance内のデータを含む辞書を返します。

ですから、このような何かする必要があります

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形式で外部キー値を設定しないということです。 値としてdictに入っていても、すべてが外部キーにあります。 なぜフォームに表示されないのでしょうか? – teconomix

+0

Hmmm ...おそらくあなたのFieldsがModelChoiceFieldsなので、model_to_dictから出てくるデータは正しいフォーマットではないでしょう。実験して調整する必要があります。 –

+0

私はfkオブジェクトをロードしようとし、dictの値を対応するオブジェクトに置き換えました。しかしまだ - 外部キーの値は、レンダリングされたフォームに表示されません... ...( – teconomix

関連する問題