LoginSignup
7
3

More than 5 years have passed since last update.

python,djangoでフォームとリストを同時に出力したい。

Last updated at Posted at 2019-03-20

python,djangoでフォームとリストを同時に出力したい。
えっ?そんなこと簡単なんじゃないのと思われるかもしれませんがちょっとコツが要ります。
まずなんで同時に出力できないの?ということを説明しますね。
urls.pyを見てみましょう。

    path('<int:pk>/', views.ListView.as_view(), name='detail'),

urlで使用できる関数は以下で定義されます。

views.ListView.as_view()



これって例えば

views.ListView.as_view(), views.FormView.as_view(),



とかやってフォームとコメントの一覧を1ページに出力しようとするとエラーが出ます。
これってdjango特有の不便さなんですかね?それともwebのフレームワークはおおむねそういうものなの?知っている方いたら教えてちょ!


というわけで、冒頭に話した
「えっ?そんなこと簡単なんじゃないのと思われるかもしれませんがちょっとコツが要ります。」

という話が浮上してきます。
というわけでふたつの関数をドッキングさせます。

リストビュー。

class ListView(generic.ListView):
    model = Post


フォームビュー。

class PostForm(forms.ModelForm):

    success_url = reverse_lazy('board:board')
    template_name = 'board/board.html'

    class Meta:
        model = Post
        fields = "__all__"       



フュージョン!!


class ListView(generic.ListView, ModelFormMixin):
    model = Post
    form_class = PostForm
    success_url = reverse_lazy('board:board')
    template_name = 'board/board.html'
    paginate_by = 15

    def get(self, request, *args, **kwargs):
        self.object = None
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = None
        self.object_list = self.get_queryset()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

詳しくは滝川成人先生のブログを見てほしいですが僕の方でも解説。
https://torina.top/detail/337/

class ListView(generic.ListView, ModelFormMixin):

ListViewをベースにしてFormをミックスします。
リストに使うモデルであるPOSTとフォーム部分に使うモデルフォームであるPostFormを定義します。

    model = Post
    form_class = PostForm

フォームとリストを使うテンプレートを定義しましょう。

    success_url = reverse_lazy('board:board')
    template_name = 'board/board.html'



上は成功時にリダイレクトするURLで下はフォームを使いたいURL。


これはページネーションのページ数。

paginate_by = 15


これはごめんなさい。分かりません!

    def get(self, request, *args, **kwargs):
        self.object = None
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = None
        self.object_list = self.get_queryset()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

super()が継承に使うものということしかわかりません!!



これはPostのリストを新着順にする魔法。

    def get_queryset(self):
        return Post.objects.order_by('-date')

一番上から古いものが表示されます。
これで基本は終わり。でもちょっと補足します。




リストをベースにしてフォームをミックスするといいましたが
フォームビューとリストビューを別個に作り、TemplateResponseMixinと書く方法があります。

class FormAndListView(FormView, ListView, TemplateResponseMixin):

でもこの方法だとListViewがベースにならないため(だと思われる)ページネーションが出来ないです。気を付けましょうね。

7
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3