Множественный поиск с внешним ключом django (Related Field got invalid lookup: icontains)
Я понимаю, что нельзя напрямую использовать иконки на внешнем ключе при поиске, но пока не нашел решения.
Вот мое представление поиска в файле views.py (я импортировал все необходимые модели):
def search(request):
# if the user actually fills up the form
if request.method == "POST":
searched = request.POST['searched']
# author__icontains part is not working
posts = Post.objects.filter(Q(title__icontains=searched) | Q(author__author__icontains=searched))
return render(request, 'blog/search.html', {'searched': searched, 'posts': posts})
else:
return render(request, 'blog/search.html', {})
Вот моя модель в model.py:
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
В основном, это не работает:
posts = Post.objects.filter(Q(title__icontains=searched) | Q(author__author__icontains=searched))
Ошибка Related Field got invalid lookup: icontains
author
is a User
object. Therefore you should work with username
, or first_name
, or some other field. Likely author
is also the value of a related_name=…
[Django-doc] that thus makes a LEFT OUTER JOIN
on another table, and thus would work on the primary key(s) of that table.
Таким образом, вы фильтруете:
def search(request):
# if the user actually fills up the form
if request.method == 'POST':
searched = request.POST['searched']
# author__icontains part is not working
posts = Post.objects.filter(
Q(title__icontains=searched) |
Q(author__username__icontains=searched)
)
return render(request, 'blog/search.html', {'searched': searched, 'posts': posts})
return render(request, 'blog/search.html')
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL
[Django-doc] to refer to the user model, than to use theUser
model [Django-doc] directly. For more information you can see the referencing theUser
model section of the documentation.
Примечание: Поиск обычно выполняется через запрос GET, поскольку это означает, что запрос хранится в строке запроса и, следовательно, в URL. Это делает удобным, например, передачу URL с запросом кому-то другому или добавление результата в закладки. POST-запросы обычно используются для действий, изменяющих состояние, или для запросов с чувствительными данными.
Эта проблема вызвана неспособностью Django обрабатывать внешние ключи с несколькими значениями для одного поля. Причина этого ограничения в том, что Django не знает, как разрешить эти конфликты, поэтому просто игнорирует их. В вашем случае, поскольку в вашей модели есть два поля, которые соответствуют критериям поиска, Django проигнорирует оба результата и отобразит пустой список.
Чтобы решить эту проблему, нам нужно добавить новый атрибут в нашу модель под названием "icontains", который будет содержать значение другого поля. Затем мы установим этот атрибут в качестве значения по умолчанию для поля "author" при запросе из базы данных. Вот как теперь должна выглядеть ваша модель:
class Post(models.Model): title = models.CharField(max_length=100) content = models.TextField() date_posted = models.DateTimeField(default=timezone.now) author = models.ForeignKey(User, on_delete=models.CASCADE) icontains = models.CharField(max_length=100, null=True, blank=True) def __str__(self): return self.title def get_absolute_url(self): return reverse('post-detail', kwargs=dict(pk=self.pk))
После этого изменения код будет работать правильно.
Для получения дополнительной информации об этом ограничении смотрите документацию Django здесь: https://docs.djangoproject.com/en/1.9/topics/db/queries/#lookups-that-span-relationships