How to get a list from a queryset in Django - django

Consider the following django code
phonenumbers = othermodel.objects.filter( company=mymodel.company,
date_overwritten__isnull=True
).values_list('id', flat=True)
This is returning another QuerySet object instead of a python list, the first object in the queryset returned is a {valuesListQuerySet} which is an empty list and this is correct because my whole model/table othermodel is currently empty
What am i missing? and how do i get just the {valuesListQuerySet} as a normal python list even if its empty

As the django doc says
If you don’t pass any values to values_list(), it will return all the
fields in the model, in the order they were declared.
Note that this method returns a ValuesListQuerySet. This class behaves
like a list. Most of the time this is enough, but if you require an
actual Python list object, you can simply call list() on it, which
will evaluate the queryset.
So you could call:
list(phonenumbers)

Related

Get values for first or last object for a model in django-admin

Model.objects.all().values() returns a list of object values.
Model.objects.all().first() - This just appears to print an object reference with id field attribute.
Is there a way to do something like: Model.objects.all().first().values()?
The following does the trick, but is there something for this purpose?
Model.objects.filter(id=Model.objects.all().last().id).values()
You can chain the .first() after the .values(), since .values(…) [Django-doc] does not return a list, but a QuerySet that is not evaluated unless you consume it.
You thus can query with:
Model.objects.values().first()
This will return a single dictionary, and the .first() will thus force evaluation.

How to get multiple objects of a model without using filter?

In Django 2.2, we can use filter() to get a QuerySet of created objects. Using list(), I can have a list of QuerySet.
In order to get an instance of a model I can use the function get(), for instance MyModel.objects.all().get(name__exact="John"). However, the get() function works only for finding a single object. If if finds 2 or more objects, it returns an exception: MultipleObjectsReturned get() returned more than one.
Since I need to process the multiple object of my model and its attributes, I would like to get a list of objects. Is it possible? For example, I want to create a list of ages from all objects with John in the attribute name.
If not, how can I access an attribute (e.g. age) of the returned QuerySet from the MyModel.objects.all().filter(name__exact="John")?
Thanks.
Use values:
instances = MyModel.objects.filter(name__exact="John")
ages = instances.values('id', 'age')
You'll get a list of dictionaries with keys id and age.

Django Array contains a field

I am using Django, with mongoengine. I have a model Classes with an inscriptions list, And I want to get the docs that have an id in that list.
classes = Classes.objects.filter(inscriptions__contains=request.data['inscription'])
Here's a general explanation of querying ArrayField membership:
Per the Django ArrayField docs, the __contains operator checks if a provided array is a subset of the values in the ArrayField.
So, to filter on whether an ArrayField contains the value "foo", you pass in a length 1 array containing the value you're looking for, like this:
# matches rows where myarrayfield is something like ['foo','bar']
Customer.objects.filter(myarrayfield__contains=['foo'])
The Django ORM produces the #> postgres operator, as you can see by printing the query:
print Customer.objects.filter(myarrayfield__contains=['foo']).only('pk').query
>>> SELECT "website_customer"."id" FROM "website_customer" WHERE "website_customer"."myarrayfield_" #> ['foo']::varchar(100)[]
If you provide something other than an array, you'll get a cryptic error like DataError: malformed array literal: "foo" DETAIL: Array value must start with "{" or dimension information.
Perhaps I'm missing something...but it seems that you should be using .filter():
classes = Classes.objects.filter(inscriptions__contains=request.data['inscription'])
This answer is in reference to your comment for rnevius answer
In Django ORM whenever you make a Database call using ORM, it will generally return either a QuerySet or an object of the model if using get() / number if you are using count() ect., depending on the functions that you are using which return other than a queryset.
The result from a Queryset function can be used to implement further more refinement, like if you like to perform a order() or collecting only distinct() etc. Queryset are lazy which means it only hits the database when they are actually used not when they are assigned. You can find more information about them here.
Where as the functions that doesn't return queryset cannot implement such things.
Take time and go through the Queryset Documentation more in depth explanation with examples are provided. It is useful to understand the behavior to make your application more efficient.

Select a value in a Django Query

I've a Django Query:-
obj = ABC.objects.filter(column1 = value)
a_list = []
for x in obj:
a_list.append(x.column2)
I want to fetch the list of values of column2 in one go., ie dont want to use the for loop. Is there any 1 straight forward query for this?
ABC.objects.filter(column1=value).values_list('column2', flat=True)
https://docs.djangoproject.com/en/1.6/ref/models/querysets/#values-list
If you don’t pass any values to values_list(), it will return all the fields in the model, in the order they were declared.
Note that this method returns a ValuesListQuerySet. This class behaves like a list. Most of the time this is enough, but if you require an actual Python list object, you can simply call list() on it, which will evaluate the queryset.

how to insert results of a queryset to a table in Django

Am trying to insert results of a queryset into another table in my views but I get the error:
TypeError at /trackdata/
int() argument must be a string or a number, not 'ValuesQuerySet'
The code is this:
def trackdata(request):
usbtrack=(Usb.history.values('evidence'))
recordscount=Usb.history.values('evidence').count()
update=Evidence_source(evidence=usbtrack,frequency=recordscount,datatype='tzworksusb')
update.save()
I'm not sure what history is and what you are trying to fetch because your QuerySet should be formed as Usb.objects.filter(evidence=request.POST['evidence']).values('evidence'), for example. See the docs.
Anyway, values('evidence') returns a list of dicts (e.g. [{'evidence': some_value,}]), so you'd need to change evidence=usbtrack to something like evidence=usbtrack[0]['evidence']. You should probably use try/except and other error checking code, as well as loops because QuerySets by definition return lists, even if there is only one row in the result set. Another alternative is values_list() with flat=True, which returns a list of your query results rather than dicts:
usbtrack = Usb.objects.filter(evidence=request.POST['evidence']).values_list('evidence', flat=True)
Evidence_source(evidence=usbtrack[0], frequency=usbtrac.count(), datatype='tzworksusb')
Finally, if I guessed your intentions correctly and you are passing 'evidence' in your request, you would simply just do this:
usbtrack_count = Usb.objects.filter(evidence=request.POST['evidence']).count()
Evidence_source(evidence=request.POST['evidence'], frequency=usbtrack_count, datatype='tzworksusb')