I have a dictionary app where words (Lemma) can be optionally composed of other words. In my models.py
, this looks like:
class Lemma(models.Model):
cf = models.CharField(max_length=200) #citation form
pos = models.ForeignKey(Pos, on_delete=models.CASCADE) #part of speech
components = models.ManyToManyField("self", symmetrical=False, blank=True) #component Lemma
I want to return two query sets:
I want to use views to pass these two lists to a template.
I'm able to get queryset 1 pretty easily, but my solutions for queryset 2 are all quite convoluted. The relevant class in my views.py
looks like this:
class CompVerb(generic.ListView):
model = Lemma
queryset = Lemma.objects.filter(
Q(pos__term="verb") & ~Q(components=None)
).order_by("cf") #queryset 1, compound verbs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
nouns = self.queryset.values_list("components")
nouns = set([Lemma.objects.get(pk=l[0]) for l in nouns])
nouns= [l for l in nouns if l.pos.term == "noun"]
context["nouns"] = nouns #queryset 2, nouns that are components of compound verbs
return context
This also leaves me with a regular list for my verbs
variable rather than a proper queryset where I can use the .order_by()
method to sort this alphabetically list by citation form.
Is there a better approach that will return a queryset object?
You can query in reverse:
class CompVerb(generic.ListView):
model = Lemma
queryset = Lemma.objects.filter(
~Q(components=None), pos__term='verb'
).order_by(
'cf'
) # queryset 1, compound verbs
def get_context_data(self, **kwargs):
return super().get_context_data(
**kwargs,
nouns=Lemma.objects.filter(
lemma__in=self.queryset, pos__term='noun'
).order_by('cf')
)
Your queryset
will however duplicate the Lemma
s that many times as there are related components
,you thus might want to use a .distinct()
[Django-doc] to prevent this.
Note: In Django, class-based views (CBV) often have a
…View
suffix, to avoid a clash with the model names. Therefore you might consider renaming the view class toCompVerbView
, instead of.CompVerb