Django filtering a queryset -
What I am trying to do is to write a query set that filters out unique parent/name combinations. I'm only interested in the first occurance of a unique parent name.
ID PARENT TYPE LIBTYPE NAME
1 1 project 1 book_a
4 4 project 2 book_b
5 4 project 2 book_c
6 4 project 2 book_d
7 4 project 4 book_c
8 5 project 2 book_e
9 5 project 4 book_e
10 7 project 0 book_f
11 7 project 0 book_g
12 7 project 6 book_h
13 6 user 1 book_i
14 6 proje开发者_开发问答ct 1 book_j
15 6 project 1 book_k
16 7 project 5 book_h
17 7 project 8 book_h
18 7 project 7 book_h
19 7 project 9 book_h
20 7 project 1 book_h
21 8 project 1 book_a
So we started with a basic queryset..
vars = Variants.objects.filter(type="project")
This removed out the lone user.. Now in pure python I would just do this to filter this sucker.
vars = Variants.objects.filter(type="project")
new_vars = []
for idx, var in vars.enumerate():
if var.name not in new_vars:
new_vars.append((var.parent,var.name))
else:
del vars[idx]
In the end I should end up with the following ID's (1,4,5,6,8,10,11,13,14,15,21) Obviously I can't enumerate on a Queryset plus I'm sure there is a way to filter this in Django.
Can someone please shed some light on how to efficiently do this in Django?
Your so-called "pure Python" solution makes no sense, I'm afraid. For a start, enumerate
is a built-in, so you would call enumerate(vars)
; secondly, you append a tuple to new_vars so var in new_vars
will never be True; and thirdly, I can't see what you're trying to do with that del
statement - you should never modify something you're iterating through.
A better solution in Python might be something like this:
var_dict = {}
for var in vars:
if var.name not in var_dict:
var_dict[var.name] = var
return var_dict.values()
which works just as well with a queryset.
If I understand correctly, though, you're after a db-level solution. That's not possible, as aggregation functions work on the whole row being selected. You can get the unique values for (parent, name)
but you can't get the ID as well - because (id, parent, name)
is not a unique combination.
Here is what I did do - Dan was right and I was a bone-head..
projects = Variant.objects.filter(type="project")
filter_list, uniq_projs = [], []
for project in projects:
if (project.name, project.parent) not in uniq_projs:
uniq_projs.append((project.name, project.parent))
filter_list.append(project.id)
projects = Variant.objects.filter(type="project", id__in=filter_list).order_by('parent__name')
Feeling so dumb..
精彩评论