はじめに
検索機能を実装する際、Qオブジェクトを用いて絞り込みを行った。ここで、Related Field got invalid lookup
というエラーが出たので原因を記録しておく。
状態
モデルはPostモデルを用意し、フィールドとして投稿者、タイトル、内容、投稿日をもつ。
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
content = models.TextField()
published_at = models.DateTimeField(auto_now_add=True)
app_name = 'app'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]
<!--検索フォーム-->
<div>
<form action="" method="get">
<a type="submit"></a>
<input name="query" value="{{ request.GET.query }}" type="search" placeholder="Search...">
</form>
</div>
<!--検索フォーム-->
q_word = self.request.GET.get('query')
で検索フォームの中身を取得し、存在する場合はQオブジェクトを用いてindex.htmlにレンダリングするobject_listを絞り込む。存在しない場合は単純にobject_listを返す。
class IndexView(generic.ListView):
model = Post
template_name = 'app/index.html'
def get_queryset(self):
q_word = self.request.GET.get('query')
if q_word:
object_list = Post.objects.filter(
Q(author__icontains=q_word) |
Q(title__icontains=q_word) |
Q(content__icontains=q_word)
)
else:
object_list = Post.objects.all()
return object_list
原因
エラーの原因はapp/views.pyのQ(author__icontains=q_word)
の部分である。views.pyのIndexViewクラスで検索の対象としてauthor、title、contentを指定しているが、models.pyのPostモデルでauthorフィールドはForeignKey()でユーザーモデルと紐づけられている。したがって、authorフィールドに紐づくモデルのフィールドを指定する必要がある。つまり、
Q(author__icontains=q_word)
ではなくQ(author__username__icontains=q_word)
と変更し、authorフィールドに紐づくUserモデルのusernameフィールドを検索対象とする必要がある。
class IndexView(generic.ListView):
model = Post
template_name = 'app/index.html'
def get_queryset(self):
q_word = self.request.GET.get('query')
if q_word:
object_list = Post.objects.filter(
Q(author__username__icontains=q_word) | # 変更!!
Q(title__icontains=q_word) |
Q(content__icontains=q_word)
)
else:
object_list = Post.objects.all()
return object_list