When implementing the search function, we narrowed down using Q objects. Here, the error Related Field got invalid lookup
appeared, so record the cause.
The model prepares a Post model, and has the poster, title, content, and post date as fields.
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
<!--Search form-->
<div>
<form action="" method="get">
<a type="submit"></a>
<input name="query" value="{{ request.GET.query }}" type="search" placeholder="Search...">
</form>
</div>
<!--Search form-->
Get the contents of the search form with q_word = self.request.GET.get ('query')
, and if it exists, use the Q object to narrow down the object_list to be rendered in index.html. If it does not exist, it simply returns 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
The cause of the error is the Q (author__icontains = q_word)
part of app / views.py. Although author, title, and content are specified as search targets in the IndexView class of views.py, the author field is associated with the user model by ForeignKey () in the Post model of models.py. Therefore, it is necessary to specify the model field associated with the author field. In other words
It is necessary to change it to Q (author__username__icontains = q_word)
instead of Q (author__icontains = q_word)
and search for the username field of the User model associated with the author field.
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) | #Change! !!
Q(title__icontains=q_word) |
Q(content__icontains=q_word)
)
else:
object_list = Post.objects.all()
return object_list