2

私がしようとしていることは次のとおりです。Userは、これまでに必要な情報でproduction(ポッドキャストエピソードとしても知られる) (このクエリではproduction_ididとなります)。ユーザがChapterMarkテンプレートに到着したとき、彼/彼女が彼/彼女のエピソードを通して話している特定の話題を指摘するために彼はcreate several timestampsになることができます。 chaptermark_idOne-To-Manyとなるので作成され、このidでは、私はそのエピソード内に望むタイムスタンプを追加できます。これを念頭に置いて、このタイプの状況に最適なアプローチはどのようなものですか?フォーム、クラスビュー、テンプレートでどのように実装できますか?ここでは、事前にDjango:ボタンをクリックするだけでクラスビューを使用して余分な入力フィールドを追加して削除します

おかげ

は私views.pyです:

from django.http import HttpResponseRedirect, Http404, HttpResponseForbidden 
from django.shortcuts import render, get_object_or_404 
from django.views.generic import View, RedirectView, TemplateView 
from django.contrib.auth.decorators import login_required 
from django.contrib.auth.mixins import LoginRequiredMixin 

from .forms.client_setup import ClientSetupForm 
from .forms.podcast_setup import PodcastSetupForm 
from .forms.episode_info import EpisodeInfoForm 
from .forms.image_files import EpisodeImageFilesForm 
from .forms.wordpress_info import EpisodeWordpressInfoForm 
from .forms.chapter_marks import EpisodeChapterMarksForm 
from .forms.show_links import ShowLinksForm 
from .forms.tweetables import TweetablesForm 
from .forms.clicktotweet import ClickToTweetForm 
from .forms.schedule import ScheduleForm 
from .forms.wordpress_account import WordpressAccountForm 
from .forms.wordpress_account_setup import WordpressAccountSetupForm 
from .forms.wordpress_account_sortable import WordpressAccountSortableForm 
from .forms.soundcloud_account import SoundcloudAccountForm 
from .forms.twitter_account import TwitterAccountForm 
from producer.helpers import get_podfunnel_client_and_podcast_for_user 
from producer.helpers.soundcloud_api import SoundcloudAPI 
from producer.helpers.twitter import TwitterAPI 

from django.conf import settings 
from producer.models import Client, Production, ChapterMark, ProductionLink, ProductionTweet, Podcast, WordpressConfig, Credentials, WordPressSortableSection, \ 
    TwitterConfig, SoundcloudConfig 

from django.core.urlresolvers import reverse 
from producer.tasks.auphonic import update_or_create_preset_for_podcast 

class EpisodeChapterMarksView(LoginRequiredMixin, View): 
    form_class = EpisodeChapterMarksForm 
    template_name = 'fc/forms_chapter_marks.html' 

    def get(self, request, *args, **kwargs): 
     initial_values = {} 
     user = request.user 

     # Lets get client and podcast for the user already. if not existent raise 404 
     client, podcast = get_fc_client_and_podcast_for_user(user) 
     if client is None or podcast is None: 
      raise Http404 

     # The production_id or the chaptermark_id must be passed on teh KWargs 
     production_id = kwargs.get('production_id', None) 
     chaptermark_id = kwargs.get('chaptermark_id', None) 
     if chaptermark_id: 
      chaptermark = get_object_or_404(ChapterMark, id=chaptermark_id) 
      production = chaptermark.production 
     elif production_id: 
      production = get_object_or_404(Production, id=production_id) 
      chaptermark = None 

     initial_values['production_id'] = production.id 

     if chaptermark is not None: 
      initial_values['chaptermark_id'] = chaptermark_id 
      initial_values['start_time'] = chaptermark.start_time 
      initial_values['title'] = chaptermark.title 

     form = self.form_class(initial=initial_values) 
     return render(request, self.template_name, {'form': form}) 

    def post(self, request, *args, **kwargs): 
     form = self.form_class(request.POST) 

     if form.is_valid(): 
      # lets get the data 
      production_id = form.cleaned_data.get('production_id') 
      chaptermark_id = form.cleaned_data.get('chaptermark_id') 
      start_time = form.cleaned_data.get('start_time') 
      title = form.cleaned_data.get('title') 

      # Get production 
      production = get_object_or_404(Production, id=production_id) 

      # if a chaptermark existed, we update, if not we create 
      if chaptermark_id is not None: 
       chaptermark = ChapterMark.objects.get(id=chaptermark_id) 
      else: 
       chaptermark = ChapterMark() 

      chaptermark.start_time = start_time 
      chaptermark.title = title 
      chaptermark.production = production 
      chaptermark.save() 

      return HttpResponseRedirect(reverse('fc:episodeshowlinks')) 

     return render(request, self.template_name, {'form': form}) 

chaptermark.py形式:

from django import forms 

class EpisodeChapterMarksForm(forms.Form): 

    production_id = forms.IntegerField(widget=forms.Field.hidden_widget, required=False) 
    chaptermark_id = forms.IntegerField(widget=forms.Field.hidden_widget, required=False) 
    start_time = forms.TimeField(required=False) 
    title = forms.CharField(max_length=200) 

chaptermarkテンプレート:

{% extends "fc/base.html" %} 
{% load crispy_forms_tags %} 


{% block content %} 

<div class="progress"> 
    <div class="progress-bar progress-bar-striped progress-bar-success active" role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" style="width: 50%"> 
    <span class="sr-only">50% Complete</span> 
    </div> 
</div> 

<div class="panel panel-default box-shadow--16dp col-sm-6 col-sm-offset-3"> 
<div class="panel-body"> 

<div class='row'> 
<div class='col-sm-12'> 

{% if title %} 
<h1 class='{% if title_align_center %}text-align-center{% endif %}'>{{ title }}<!-- : {{ get.clientsetup.company_name }} --></h1> 
{% endif %} 
{% if subtitle %} 
<h3 class='{% if subtitle_align_center %}text-align-center{% endif %}'>{{ subtitle }}</h4> 
{% endif %} 

<h5>Chapter Marks</h5> 

<form method='POST' action=''>{% csrf_token %} 
{{ form|crispy }} 

<hr/> 

<button type="submit" class="btn btn-primary box-shadow--6dp"><i class="fa fa-chevron-right pull-right"></i> Continue 
</button> 

</form> 
</div> 
</div> 

</div> 
</div> 

{% endblock %} 

---------------------- UPDATE ------------------- ------

views.pyにあった:

@login_required 
def episodechaptermarks(request): 
    title = 'Podcast' 
    title_align_center = True 
    subtitle = 'Setup | Add Episode' 
    subtitle_align_center = True 
    form = ChapterMarksForm(request.POST or None) 
    context = { 
     "title": title, 
     "subtitle": subtitle, 
     "form": form 
    } 

    if form.is_valid(): 

     instance = form.save(commit=False) 

     start_time = form.cleaned_data.get("start_time") 
     title = form.cleaned_data.get("title") 

     instance.start_time = start_time 
     instance.title = title 

     instance.user = request.user 

     instance.save() 

     return render(request, "pod_funnel/forms_chapter_marks.html", context) 

    else: 

     return render(request, "pod_funnel/forms_chapter_marks.html", context) 

ModelForm:本質的には

from django import forms 

from producer.models import ChapterMark 

class ChapterMarksForm(forms.ModelForm): 

    class Meta: 

     model = ChapterMark 
     fields = ['start_time', 'title'] 

    def clean_start_time(self): 
     start_time = self.cleaned_data.get('start_time') 

     return start_time 

    def clean_title(self): 
     title = self.cleaned_data.get('title') 

     return title 

答えて

1

、あなたのproductionオブジェクトが0のシリーズを持っていますは、FKを介して関連しています。 CRUDのビューはproductionレベルで必要です。あなたのモデルがすでに作成されていると仮定しましょう。私の経験からいくつかのことがありますが、正しい方向に向けると思います。モデルを反映するフォームオブジェクトを作成するときに

  1. 絶対に必要な場合を除きFormクラスを使用することはありません。不必要な複雑さの必要性を導入し、エラーの扉を開くことになります。 ModelFormを使用すると、オブジェクトをビューから直接DBに保存して、クリーニング、検証などを管理するのに役立ちます。さらに、これらはすべての種類のジェネリック・ビューに簡単にメッシュ表示できます。

  2. この種類の関係(そのオブジェクトを返す特定の型のモデルオブジェクトの数が異なるモデルオブジェクト)では、Djangoは強力だが難しいinlineformset_factoryを提供します。これにより、このような関係に必要な一連のインラインフォームが作成されます。

  3. モデル(production)とそれに関連する別のもの(timestamp)があります。これらを同時に保存し、クリーニングや検証を実行し、実際にこの関係全体にCRUD機能を提供する必要があります。このために、またはから複雑なビューを作成し、インラインモデルの場合はdjango-extra-viewsとその汎用CBVを使用できます。CreateWithInlinesViewUpdateWithInlinesViewをサブクラス化することができます。どうして?ほとんどのDjango開発者は、書式設定の実装が難しいことに同意します。

だから、あなたがこの

from extra_views.advanced import CreateWithInlinesView, InlineFormSet, UpdateWithInlinesView 


class TimeStampsInline(InlineFormSet): 
    model = models.TimeStamp 
    form = TimeStampForm # If you haven't created a custom ModelForm, can also specify "fields= ['field_1','field_2',...] and the CBV will create a ModelForm 
    extra = 0 


class ProductionCreate(CreateWithInlinesView): 
    model=models.Production 
    inlines = [TimeStampsInline] 
    success_url = reverse('production-list') # the url to return to on successful create 
    exclude = ['created_by'] # render all fields except this in form 
    template_name = 'myapp/update.html' 

class ProductionUpdate(UpdateWithInlinesView): 
    model=models.Production 
    inlines = [TimeStampsInline] 
    success_url = reverse('production-list') 
    exclude = ['created_by'] 
    template_name = 'myapp/update.html' 

あなたのテンプレート(複数可)を行うことができますどのようにの簡易版を与えるためにフォームセットを持つ仕様で構築する必要があります。そこにはドキュメンテーションとチュートリアルがあります。

これはすでに大量に消化されていますが、おそらく一般的な考えを得るでしょう。最初から馬を作りません;)

+0

お返事ありがとうございました!私の 'ChapterMarkView'クラスを設定する前に、私は' ModelForm'(チェック・アップデート)ビューとして持っていましたが、遠くには行きませんでした。 'ModelForm'に戻って私が持っていたテンプレートをあなたが提供したテンプレートに置き換えてそこから行くことをお勧めしますか?私はかなり新しいdjangoです...あなたはそれを通して私を導くことができますか?それを感謝します。 – wlmrlsda

+0

これらの一般的なビューでは、 'form'を指定することはできず、代わりに' fields'または 'exclude'(除外するフィールドのリスト)を指定すれば、ビューは独自のModelFormを作成します。標準的なフォームを使用してモデルオブジェクトを表現すると、それに付属するすべての組み込みのクリーニングと検証が失われます。つまり、フォームを介して送信されたデータを保存しようとする可能性があります。これは、すべてのデータベース制約が満たされないと失敗します。それはいくつかの大きな問題のために、不必要にドアを開けています。 ModelFormはDjangoの巨大な部分であり、よく知る価値があります:) –

+0

Ok、それを試してみましょう。私がこのプロセスを通して何か質問をするために戻ってきたらどうか?また、 'id'に関しては、' ModelForm'の中でそれぞれを作成する必要がありますか?例えば、私の 'Forms'には' production_id = forms.IntegerField(widget = forms.Field.hidden_​​widget、required = False) 'と' chaptermark_id = forms.IntegerField(widget = forms.Field.hidden_​​widget、requiredがあります。 = False) ' – wlmrlsda

関連する問題