はじめに
非同期通信でイイね機能を実装してみたの記事で開発を進めていたところ、非ログインユーザーでArticleDetailViewへリクエストした際に、ブラウザ側でAnonymousUser object is not iterableエラーが発生してしまった。そこで、この記事では'AnonymousUser' object is not iterableエラーの原因と対処法についてまとめます。
'AnonymousUser' object is not iterableエラー
これは未ログインユーザーによるリクエスト処理が正常に行われない時に発生するエラーです。もう少し掘り下げると、このAnonymousUserはUserモデルのインスタンスとして扱うことができず、例えばUserモデルで定義したカラム属性などは扱うことができません。
対処法
改めて元々のコードを見てみます。
class ArticleDetailView(generic.DetailView):
model = Article
template_name = 'article_detail.html'
def get_context_data(self, **kwargs): #ユーザが既にイイねしているかどうかの判断
context = super().get_context_data(**kwargs)
like_for_article_count = self.object.likeforarticle_set.count()
#記事に対するイイね数
context['like_for_article_count'] = like_for_article_count
#ユーザがイイねしているかどうか
if self.object.likeforarticle_set.filter(user=self.request.user).exists():
context['is_user_liked_for_article'] = True
else:
context['is_user_liked_for_article'] = False
return context
ここで、問題となっているポイントは.filter(user=self.request.user)
の部分です。request.userがAnonymousUserである場合、ここの部分で問題が発生してしまいます。
AnonymousUserであるかどうかの判別方法はユーザー.id
がNoneであるかどうかで判別することができます。そのため、get_context_dataメソッドを下記のように修正することで対処できました。
def get_context_data(self, **kwargs): #ユーザが既にイイねしているかどうかの判断
context = super().get_context_data(**kwargs)
like_for_article_count = self.object.likeforarticle_set.count()
#記事に対するイイね数
context['like_for_article_count'] = like_for_article_count
#非ログインユーザーの場合
if self.request.user.id is None:
context['is_user_liked_for_article'] = False
#ログインユーザがイイねしているかどうか
elif self.object.likeforarticle_set.filter(user=self.request.user).exists():
context['is_user_liked_for_article'] = True
else:
context['is_user_liked_for_article'] = False
return context