LoginSignup
0
4

More than 3 years have passed since last update.

【Django】Qオブジェクトを用いた際のエラー(Related Field got invalid lookup)

Last updated at Posted at 2020-06-24

はじめに

 検索機能を実装する際、Qオブジェクトを用いて絞り込みを行った。ここで、Related Field got invalid lookupというエラーが出たので原因を記録しておく。

状態

モデルはPostモデルを用意し、フィールドとして投稿者、タイトル、内容、投稿日をもつ。

app/models.py
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/urls.py
app_name = 'app'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
]
app/index.html
    <!--検索フォーム-->
    <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を返す。

app/views
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フィールドを検索対象とする必要がある。

app/views
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
0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4