起こったこと
CustomerManagementViewはログインユーザーでアクセスできるのに、CustomerDetailViewはなぜか403エラーが出る。
なお、ログインしていないユーザーはログイン画面に遷移し、スーパーユーザーはDetailViewも見れるのでtemplatesなどには問題はないと考えた。
class CustomerDetailView(LoginRequiredMixin, DetaiView):
model = Reservation
template_name = "managements/customer_detail.html"
customer_detail = CustomerDetailView.as_view()
class CustomerManagementView(LoginRequiredMixin, ListView):
template_name = "managements/customer_management.html"
model = Reservation
paginate_by = 10
def get_queryset(self, **kwargs):
queryset = Reservation.objects.order_by("-date")
return queryset
customer_management = CustomerManagementView.as_view()
まずsettings.py、特にmiddlewareを確認したが、i18nやwhitenoise以外は追加していないので、こちらも問題なさそう。
また、管理者だけが見れる、管理画面で同じような構成のViewがあるが、こちらも問題なく見れる。
class DetailView(UserPassesTestMixin, DetailView):
model = Reservation
template_name = "managements/detail.html"
def test_func(self):
# スーパーユーザーでなければ403ページ
return self.request.user.is_superuser
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
reservation = self.get_object()
related_objects = reservation.changed_user.all() # ManyToManyFieldに関連するオブジェクトのリストを取得
context['related_objects'] = related_objects
return context
detail = DetailView.as_view()
そのためLoginRequiredMixinに原因があると思い、UserPassesTestMixinに変更するも、以下のエラーが出る。
class CustomerDetailView(UserPassesTestMixin, LoginRequiredMixin, DetailView):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases UserPassesTestMixin, LoginRequiredMixin, DetailView
原因と対処法
原因はDetailViewのimportにあった。
DetailViewは以下のようにimportしていて、管理画面のclass DetailView(UserPassesTestMixin, DetailView):継承したDetailViewは問題なかったが、なぜかclass CustomerDetailView(LoginRequiredMixin, DetaiView):の方はうまく継承できなかった。
from django.views.generic.detail import DetailView
こっちの形でDetailViewをimportすると後者はうまく継承できたが前者が逆に継承できなくなった。
from django.views.generic import DetailView as dt
そのため2つを分けてimportすることで解決した。なぜこのようなことが起こるのかは未だわからない。
from django.views.generic.detail import DetailView
#なぜかcustomer_detailのDetailViewだけgeneric.detailを使うとログインユーザーでも403エラーが出るのでこっちを使う(スーパーユーザーは大丈夫)
from django.views.generic import DetailView as dt
Chatgptfrom django.views.generic import DetailView
とfrom django.views.generic.detail import DetailView
のどちらを使うかによってMRO(Method Resolution Order)エラーが発生するというのは興味深い現象です。通常、これらは同じクラスをインポートしているため、機能的には同じはずです。しかし、Djangoの内部実装や特定のバージョンに依存する問題があるかもしれません。