Django 新規ページ作成の流れ

今回の記事では、Django開発において、新規ページを作成する際のスムーズな流れを書きます。

### 新規ページ作成フロー

1. views.py に一旦TemplateViewで view の class を作成する(template_nameのみのシンプルなもの)
2. urls.pyに作成した view を読み込んで、ルーティングを実装する
3. viewの template_name に記述したパスにhtmlファイルを作成する
4. view に get_context_data を追加して、あらかじめ必要なデータを投げておく
5. htmlファイルにテンプレートを作成して、あらかじめ投げたデータなどを受け取って、フロントエンドを作成していく。
6. formやリクエストなどの処理やjs処理などを実装する
7. views.py に戻り、viewを更新する。-> 必要に応じて、UpdateViewやListView,CreateView, DetailViewなど
8. 必要に応じて、urls.pyを編集する
9. viewにpostに対する処理などを記述する
10. post処理とフロントエンドのリクエスト部分で、デバッグを繰り返し、処理がうまくいくようにコードを書いていく
11. viewにUserPassesTestMixinなどで、権限関係の制限などを追加する
12. 完成！

* あらかじめ、既にあるページから新しいページへ飛ぶリンク（aタグ）を作成しておくと、開発フローが楽になります。


それでは、実例とともに、上記のフローをさらっていきましょう！

### ブログで新しく記事の一覧ページを 作成する場合

1. article/views.py に 以下を追加

```article/views.py
from django.views.generic import TemplateView

class ArticleListView(TemplateView):
   
    template_name = "article/list.html"

article_list = ArticleListView.as_view()
```

2.urls.py に以下を追加

```article/urls.py
from django.urls import path, include
from . import views

app_name= 'article'
urlpatterns = [
    path('article/list', views.article_list, name='article_list'),
]
```

3.templatesフォルダのarticleフォルダ配下に `list.html` を作成

4.viewにget_context_dataを追加して、あらかじめ必要なデータを投げる

```article/views.py

from django.views.generic import TemplateView

class ArticleListView(TemplateView):
   
    template_name = "article/list.html"

    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        hoge    = Hoge.objects.all().order_by('created')
        context['hoge'] = hoge
        return context

article_list = ArticleListView.as_view()
```

5.htmlファイルにテンプレートを作成して、あらかじめ投げたデータなどを受け取って、フロントエンドを作成していく。
6.formやリクエストなどの処理やjs処理などを実装する

- **フロントエンドの部分は割愛**


7.views.pyを更新する

```article/views.py

from django.views.generic import TemplateView, ListView
from .models import Article

class ArticleListView(ListView):
   
    template_name = "article/list.html"
    model = Article
    paginate_by = 15

    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        hoge    = Hoge.objects.all().order_by('created')
        context['hoge'] = hoge
        return context

article_list = ArticleListView.as_view()
```

8.必要に応じて、urls.pyを編集する

- **必要がないため割愛**


9. viewにpostに対する処理などを記述する

```article/views.py

from django.views.generic import TemplateView, ListView
from .models import Article
from django.http import HttpResponseBadRequest, HttpResponseRedirect

class ArticleListView(ListView):
   
    template_name = "article/list.html"
    model = Article
    paginate_by = 15

    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        hoge    = Hoge.objects.all().order_by('created')
        context['hoge'] = hoge
        return context

    def post(self, request, *args, **kwargs):
        post = request.POST
        if 'add_comment' in post:
            body = post['body']
            article_id = int(post['article_id'])
            comment = Comment()
            comment.article_id = article_id
            comment.body = body
            comment.save()
            url = request.META['HTTP_REFERER']
            return HttpResponseRedirect(url)
        return HttpResponseBadRequest()

article_list = ArticleListView.as_view()
```

10.post処理とフロントエンドのリクエスト部分で、デバッグを繰り返し、処理がうまくいくようにコードを書いていく

- **ここは割愛**

11.viewに権限関係などを追加

```article/views.py

from django.views.generic import TemplateView, ListView
from .models import Article
from django.http import HttpResponseBadRequest, HttpResponseRedirect
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin

class ArticleListView(LoginRequiredMixin, UserPassesTestMixin, ListView):
   
    template_name = "article/list.html"
    model = Article
    paginate_by = 15

    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        hoge    = Hoge.objects.all().order_by('created')
        context['hoge'] = hoge
        return context

    def post(self, request, *args, **kwargs):
        post = request.POST
        if 'add_comment' in post:
            body = post['body']
            article_id = int(post['article_id'])
            comment = Comment()
            comment.article_id = article_id
            comment.body = body
            comment.save()
            url = request.META['HTTP_REFERER']
            return HttpResponseRedirect(url)
        return HttpResponseBadRequest()

    # return False で 403
    def test_func(self):
        return self.request.user.profile.type in [1,2,3]

article_list = ArticleListView.as_view()
```

ざっと上記の流れで新規ページを作っていくのがスムーズかと思います。
ただし、新規ページを作成する時点で、どのようなデータをどのようなkeyで投げ、どのように受け取り処理するかなど全て決まっている場合は、

1. views.py
2. urls.py
3. template

の流れで一つ一つを完成させながら進めるのがいいかと思いますが、
新規ページでかつ 新しい要素が入ってくる場合、必ずといっていいほどエラーは起きるものなので、一つずつ進めていくのが、最終的に、開発時間を短縮され、かつスムーズに進められると思います。