画像を利用した本の投稿
はじめに
前回の続きで、画像を利用することができるようになったので、それを利用してユーザーが本の投稿をできるようにします。
ログイン状態の判定をする
ログインしている状態でないと本の投稿やデータの閲覧ができないようにします。
まずbook/views.pyに以下を追加します。
from django.contrib.auth.mixins import LoginRequiredMixin # 追加 class ListBookView(LoginRequiredMixin, ListView): # 追加 template_name = 'book/book_list.html' model = Book paginate_by = ITEM_PER_PAGE
追加した継承のLoginRequiredMixinは一番左に記述しましょう。
ログインしていない状態ではaccounts/login/に遷移させることができます。
また、他のclassの継承にもLoginRequiredMixinを追記しておきましょう。
自分で投稿したデータのみ編集可能にする
まずはbook/models.pyに以下を追加します。
class Book(models.Model): title = models.CharField(max_length=100) text = models.TextField() thumbnail = models.ImageField(null=True, blank=True) category = models.CharField( max_length=100, choices = CATEGORY ) user = models.ForeignKey('auth.User', on_delete=models.CASCADE) # 追加 def __str__(self): return self.title
サーバーを立ち上げ、127.0.0.1:8000/admin/にアクセスします。それから適当なユーザーを選択します。
この赤い部分がユーザーのidとなっています。これを確認すれば、以下のコマンドを実行します。
python3 manage.py makemigrations python3 manage.py migrate
再度選択しろと言われたら今度は1を選択します。
ではここからログインしているユーザーしか編集できないようにするための実装をしていきます。まずはbook/views.pyに以下の記述を追加します。
from django.core.exceptions import PermissionDenied # 追加 class UpdateBookView(LoginRequiredMixin, UpdateView): template_name = 'book/book_update.html' model = Book fields = {'title', 'text', 'category', 'thumbnail'} success_url = reverse_lazy('list-book') def get_object(self, queryset=None): # 追加 obj = super().get_object(queryset) # 追加 if obj.user != self.request.user: # 追加 raise PermissionDenied # 追加 return obj # 追加
追加した if obj.user != self.request.userについて見ていきます。obj.userはUpdateBookViewで呼び出された書籍の登録をしたユーザーを表しており、self.request.userは現在ログイン中のユーザーを表しています。もし一致していなければraise PermissionDeniedの処理を行うといったものです。
ここでraiseは例外を出すときに利用します。また、PermissionDeniedはDjangoが用意している例外です。
サーバーを立ち上げて登録したユーザーと別ユーザーで編集してみましょう。
以下のように例外がスローされました。
また、書籍登録したユーザーが編集を行ってデータを更新した際のページ遷移先を設定します。book/views.pyを以下のように編集します。
class UpdateBookView(LoginRequiredMixin, UpdateView): template_name = 'book/book_update.html' model = Book fields = {'title', 'text', 'category', 'thumbnail'} success_url = reverse_lazy('list-book') # 削除 def get_object(self, queryset=None): obj = super().get_object(queryset) if obj.user != self.request.user: raise PermissionDenied return obj def get_success_url(self): # 追加 return reverse('detail-book', kwargs={'pk': self.object.id}) # 追加
これで編集についてはできたので、削除についても以下のようにしましょう。
class DeleteBookView(LoginRequiredMixin, DeleteView): template_name = 'book/book_confirm_delete.html' model = Book success_url = reverse_lazy('list-book') def get_object(self, queryset=None): obj = super().get_object(queryset) if obj.user != self.request.user: raise PermissionDenied return obj
また、Bookモデルにuserを追加したので、formにユーザーの情報を追加するため、book/views.pyに以下を追加します。
class CreateBookView(LoginRequiredMixin, CreateView): template_name = 'book/book_create.html' model = Book fields = {'title', 'text', 'category', 'thumbnail'} success_url = reverse_lazy('list-book') def form_valid(self, form): # 追加 form.instance.user = self.request.user # 追加 return super().form_valid(form) # 追加
これで本を投稿したユーザーしか編集することができないようにすることができました。
おわりに
今回は本を投稿したユーザーのみが編集、削除できる仕組みを実装しました。また、登録した人と別のユーザーが編集しようとすると例外を発生させることも行いました。
次回はトップページを新しい順、評価の高い順に並び替えること、ページネーションをつけて見やすいトップページにしていきます。