8

更新:解決策は別の回答として見つけることができます

ユーザーがテレビ番組をデータベースに追加できるようにするDjangoフォームを作成しています。これを行うために、Tvshowモデル aTvshowModelFormを用意し、一般的なクラスベースのビューCreateTvshowView/UpdateTvshowViewを使用してフォームを生成します。

ここで問題が発生します。たとえば、ユーザーがゲーム オブ スローンズなどの番組をデータベースに追加したいとします。このタイトルのショーが既に存在する場合は、これが実際にデータベース内のショーとは異なることを確認するようユーザーに促し、同様のショーが存在しない場合はデータベースにコミットします。この確認をどのように処理するのが最善ですか?

私の実験のいくつかは以下のコードに示されていますが、おそらく私はこれを間違った方法で行っています. 私の解決策の基本は、hidden field を含めるforceことです。ユーザーがこのデータをコミットしたいと確信している場合は、1 に設定する必要があります。これにより、ユーザーが 1 であるかどうかを判断して、もう一度送信をクリックしたため、保存したいとのことでした。

これを解決する方法について、あなたの考えを聞きたいです。

ビュー.py

class TvshowModelForm(forms.ModelForm):
    force = forms.CharField(required=False, initial=0)
    def __init__(self, *args, **kwargs):
        super(TvshowModelForm, self).__init__(*args, **kwargs)

    class Meta:
        model = Tvshow
        exclude = ('user')

class UpdateTvshowView(UpdateView):
    form_class = TvshowModelForm
    model = Tvshow
    template_name = "tvshow_form.html"

    #Only the user who added it should be allowed to edit
    def form_valid(self, form):
        self.object = form.save(commit=False)
        #Check for duplicates and similar results, raise an error/warning if one is found     
        dup_list = get_object_duplicates(Tvshow, title = self.object.title)
        if dup_list:
            messages.add_message(self.request, messages.WARNING, 
'A tv show with this name already exists. Are you sure this is not the same one? Click submit again once you\'re sure this is new content'
               )
#            Experiment 1, I don't know why this doesn't work
#            form.fields['force'] = forms.CharField(required=False, initial=1)

#            Experiment 2, does not work: cleaned_data is not used to generate the new form
#            if form.is_valid():
#                form.cleaned_data['force'] = 1

#            Experiment 3, does not work: querydict is immutable
#            form.data['force'] = u'1'

        if self.object.user != self.request.user:
            messages.add_message(self.request, messages.ERROR, 'Only the user who added this content is allowed to edit it.')

        if not messages.get_messages(self.request):
            return super(UpdateTvshowView, self).form_valid(form)
        else:
            return super(UpdateTvshowView, self).form_invalid(form)
4

5 に答える 5

4

解決

ここに回答として投稿されたアイデア、特にアレクサンダー・ラリコフとクリス・ローラーによるアイデアの助けを借りてこれを解決したので、他の人が恩恵を受けるように最終的な解決策を投稿したいと思います。

CBVでこれができることがわかり、むしろ気に入っています。(私はすべてを OOP のままにしておくのが好きなので) また、フォームを可能な限り一般的なものにしました。

まず、次のフォームを作成しました。

class BaseConfirmModelForm(BaseModelForm):
    force = forms.BooleanField(required=False, initial=0)

    def clean_force(self):
        data = self.cleaned_data['force']
        if data:
            return data
        else:
            raise forms.ValidationError('Please confirm that this {} is unique.'.format(ContentType.objects.get_for_model(self.Meta.model)))

class TvshowModelForm(BaseModelForm):            
    class Meta(BaseModelForm.Meta):
        model = Tvshow
        exclude = ('user')

"""
To ask for user confirmation in case of duplicate title
"""
class ConfirmTvshowModelForm(TvshowModelForm, BaseConfirmModelForm):
    pass   

そして今、適切なビューを作成しています。ここで重要なのは、form_class 変数を使用するのではなく、get_form_class を発見したことです。

class EditTvshowView(FormView):       
    def dispatch(self, request, *args, **kwargs):
        try:
            dup_list = get_object_duplicates(self.model, title = request.POST['title'])  
            if dup_list:         
                self.duplicate = True
                messages.add_message(request, messages.ERROR, 'Please confirm that this show is unique.')
            else:
                self.duplicate = False
        except KeyError:
            self.duplicate = False
        return super(EditTvshowView, self).dispatch(request, *args, **kwargs)

    def get_form_class(self):
        return ConfirmTvshowModelForm if self.duplicate else TvshowModelForm

"""
Classes to create and update tvshow objects.
"""
class CreateTvshowView(CreateView, EditTvshowView):  
    pass

class UpdateTvshowView(EditTvshowView, UpdateObjectView):
    model = Tvshow  

これが同様の問題を抱えている他の人に役立つことを願っています。

于 2012-08-09T12:17:49.003 に答える
3

回答として掲載させていただきます。フォームのcleanメソッドでは、必要な方法でユーザーのデータを検証できます。次のようになります。

def clean(self):
    # check if 'force' checkbox is not set on the form
    if not self.cleaned_data.get('force'):
        dup_list = get_object_duplicates(Tvshow, title = self.object.title)
        if dup_list:
            raise forms.ValidationError("A tv show with this name already exists. "
                                        "Are you sure this is not the same one? "
                                        "Click submit again once you're sure this "
                                        "is new content")
于 2012-07-31T08:10:56.283 に答える
1

ユーザーのセッションにPOSTデータを貼り付け、確認を処理する別のビューにPOSTする単純な確認/拒否フォームを含む確認ページにリダイレクトできます。更新が確認されたら、POSTデータをセッションから引き出し、通常どおり処理します。更新がキャンセルされた場合は、セッションからデータを削除して次に進みます。

于 2012-07-30T20:07:56.247 に答える
1

私は似たようなことをしなければならず、Jquery Dialog (フォームデータが「重複」するかどうかを示すため) と Ajax (必要な検証を行い、問題があった場合に返すビューに投稿するため) を使用してそれを行うことができました。データが重複している可能性がある場合、重複したエントリが表示された場所にダイアログが表示され、[確認] または [キャンセル] の 2 つのボタンがあります。誰かが「確認」にヒットした場合は、元の送信を続行できます (たとえば、jquery を使用してフォームを送信します)。そうでない場合は、ダイアログを閉じて、すべてをそのままにしておきます。

私の説明がお役に立てば幸いです....これを行うのに助けが必要な場合は、例をコピーできるように教えてください。

于 2012-07-31T12:06:53.823 に答える