I have a custom manager that returns a ranked by weights query:
class MyManager(models.Manager):
def search(self, query, fa, fb=None, fc=None, fd=None, qs=None):
try:
if not (1 in [c in query for c in '&|()!*:"']):
query = " & ".join([f"{q}:*" for q in query.split()])
vector = SearchVector(*fa, weight="A", config="english")
if fb:
vector += SearchVector(*fb, weight="B", config="english")
if fc:
vector += SearchVector(*fc, weight="C", config="english")
if fd:
vector += SearchVector(*fd, weight="D", config="english")
query = SearchQuery(query, search_type="raw")
qs = (
qs.annotate(search=vector, rank=SearchRank(vector, query))
.filter(search=query)
.order_by("-rank", "-id")
.distinct("rank", "id")
)
except (ProgrammingError, UnboundLocalError):
qs = qs.none()
return qs
But if I try to search on related fields of different models, I get duplicate results. Is there a way around it?
```
class Case(models.Model):
machine = models.ForeignKey(Machine)
user = models.ForeignKey(Profile)
objects = MyManager()
class Profile(models.Model):
user = models.OneToOneField(User)
class CaseListView(ListView):
model = Case
def get_queryset(self):
query = self.request.GET.get("query", None)
if query:
qs = self.model.objects.all()
fa = (
"id",
"machine__serial_number",
"machine__company__name",
"user__user__first_name",
"user__user__last_name",
)
fb = ("hashtags",)
fc = ("caseprogress__desc",)
qs = self.model.objects.search(
query, fa, fb, fc, qs=qs
)
return qs