I have some python code:
UnitTestCollection.objects.filter(unit__type=unit_type)
which outputs data in format:
<QuerySet [<UnitTestCollection: VALUE1>, <UnitTestCollection: VALUE2>...
How can I extract a list of the values only i.e.
[VALUE1, VALUE2....]
Why not a simple list comprehension?
qs = UnitTestCollection.objects.filter(unit__type=unit_type)
my_values = [item.field_name for item in qs]
Or use values_list() to just fetch the specific field for each item directly in your queryset, with the advantage of lazy evaluation:
qs = UnitTestCollection.objects.filter(unit__type=unit_type)\
.values_list('field_name', flat=True)
values_list is better than a list comprehension because querysets are lazily evaluated. They won't be executed until you actually need them.
queryset = UnitTestCollection.objects.filter(unit__type=unit_type).values_list('<insert field>', flat=True)
This will return [field1, field2, field3...]
if you use .values('<insert field>') you'll get [{field: field value1}, {field: field value2}, {field: field value3}...]
Related
I have the following code.
queryset = Registry.objects.filter(
epas_id__contains=uuid_obj_id
).values_list('pk', flat=True)
Based on my data, this correctly returns the following:
<QuerySet [UUID('d9a0977c-5bc0-4667-af24-5e95b83761d4'), UUID('b2d0f086-0a55-44cc-b1ba-3ebf598d24ae')]>
But what I want to do is extract just the values of pk in a list, so something like this:
['d9a0977c-5bc0-4667-af24-5e95b83761d4', 'b2d0f086-0a55-44cc-b1ba-3ebf598d24ae']
Any thoughts and help on how I can achieve this would be appreciated.
We can work with list comprehension, and call str(…) on each element, like:
queryset = Registry.objects.filter(
epas_id__contains=uuid_obj_id
).values_list('pk', flat=True)
result = [str(pk) for pk in queryset]
I have the following case. I have a form with 3 fields which are submitted with POST method. Then the fields are captured and a search using Q is made on the database:
query = Model.objects.filter( Q(field1=field1) & Q(field2=field2) & Q(field3=field3))
The problem is that I would like to dynamically use the fields that are filled not the empty ones. That means that the query will contain one or two or three criteria depending on the user.
I have managed to perform the search I describe with nested if but considering adding extra fields it gets bigger and bigger.
thanks
You can write generic function to generate a query based on fields passed-in.
def generate_query(**kwargs):
query = Q()
for database_field, value in kwargs.items():
query_dict = {database_field:value}
if value:
query &= Q(**query_dict)
return query
And use it:
data = {"name":"john", "age__gte":25} # your post data
query = generate_query(**data)
objects = SomeModel.objects.filter(query)
# generally: SomeModel.objects.filter(request.POST)
Consider you have query field like below:
field = {'field1': 'value1', 'field2': 'value2', 'field3': None}
You can filter to remove null field as below:
non_empty_field = dict(filter(lambda x: x[1], field.items())) # output: {'field1': 'value1', 'field2': 'value2'}
For performing and query you can write
Model.objects.filter(**non_empty_field) # equivalent to Model.objects.filter(field1='value1', field2='value2')
to perform and query you don't need Q() object
For performing or query you can write:
Model.objects.filter(eval('|'.join(['(Q({}="{}"))'.format(i,j) for i,j in non_empty_field.items()])))
according to current field example above query will be equivalent to:
Model.objects.filter(Q(field1=value1) | Q(field2=value2))
id_list = Foo.objects.values_list('id', flat=True)
name_list = Foo.objects.values_list('name', flat=True)
Can I get the two list conveniently, efficiently?
If by efficiently you mean in a single query, then you can get both attributes in one call and use zip to decompose them into separate lists:
values = Foo.objects.values_list('id', 'name')
id_list, name_list = zip(*values)
I am trying to run a queryset with the value of the filter being the values inside a dictionary.
latest_entries = Entry.objects.filter(zipcode__in=nearestzips.values())
print latest_entries
>>>TypeError: Cannot use a multi-field GeoValuesQuerySet as a filter value.
second attempt
latest_entries = Entry.objects.filter(zipcode__in=nearestzips.values_list('code', flat=True))
print latest_entries
>>>ProgrammingError: invalid reference to FROM-clause entry for table "cities_postalcode" HINT perhaps you meant to reference the table alias"u0"
How can I accomplish this? Should I just take the extra step of creating a new list and appending the dictionary values into the list? And then run the queryset on the list? I'm not sure what to do.
EDIT:
when I print nearestzips I get:
[<PostalCode:97201>,<PostalCode:97202>]
BUT, when I print nearestzips.values(), I get:
[distance:0, code: 97201, name: Portland, subregion: Multnomah] etc.
Looks like the nearestzips is a subclass of the QuerySet which is lost some compatibility. Try to convert values_list() to the simple python list:
zip_codes = list(nearestzips.values_list('code', flat=True))
latest_entries = Entry.objects.filter(zipcode__in=zip_codes)
I need to re-order a Django queryset, because I want to put None values at the bottom of an ORDER BY DESC query on a FloatField.
Unfortunately, I'm struggling to find an elegant way to manipulate a Django queryset. Here's what I have so far:
cities = City.objects.filter(country__id=country.id).order_by('value')
if cities.count() > 1:
cities_sorted = cities
del manors_sorted[:]
for city in cities:
cities_sorted += city
# Add code to
cities = cities_sorted
Currently, this fails with 'QuerySet' object does not support item deletion.
Any idea how I can copy and re-order this QuerySet to put None items last?
The queryset will be evaluated to a list, if you eg. call list() on it:
cities_sorted = list(cities)