Select a value in a Django Query - django

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.

Related

Is there any way I can avoid iterating over a query set with single value?

I get a queryset object every time i want some data from models.
So when i say,
"items = Items.object.get(value=value)"
I get --
"<QuerySet [<Item-name>]>"
I have to iterate through the queryset object to get the data and I do that with
"items[0]"
Is there any way I can avoid this?
Edit: I meant "items = Items.object.filter(value=value)"
first of all items = Items.objects.get(value=value) does not return a queryset,
rather it returns an object of <Items: Items object (1)>
To get the first(or just one result) or last date from the object, do this Items.objects.first() or Items.objects.last()
To get the desired data without using its index position, then you can filter it like this Items.objects.filter(value=value)
You are mistaken. items = Items.object.get(value=value) will not give you a queryset, but an object. items = Items.object.filter(value=value)
would give you a queryset.
Filter method will always give you a queryset, because; in order to minimize the need of database hits, django considers you might add additional filters through your code. So if you not execute that queryset, e.g. by using list(your_queryset) django never hits the database.
# when you are using 'get' in your query, you don't need to iterate, directly get an access to the field values
try:
items = Items.object.get(value=value)
except Items.DoesNotExist:
items = None
if items:
print(items.value)

How to get a list from a queryset in 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)

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')

How to get a particular attribute from queryset in Django in view?

I have a query like this:
file_s = Share.objects.filter(shared_user_id=log_id)
Now, I want to get the files_id attribute from file_s in Django view. How can I do that?
Use values() to get particular attribute which will return you list of dicts, like
file_s = Share.objects.filter(shared_user_id=log_id).values('files_id')
EDIT: If you want only one attribute then you can use flat=True to suggest to return just list of values. However, make sure in what order the list will be.
file_s = Share.objects.filter(shared_user_id=log_id).values_list('files_id', flat=True).order_by('id')
Your Share.objects.filter() call returns a Djagno QuerySet object which is not a single record, but an iterable of filtered objects from the database with each item being a Share instance. It's possible that your filter call will return more than one item.
You can iterate over the QuerySet using a loop such as:
for share in files_s:
print share.files_id
If you know that your query is only expected to return a single item, you could do:
share = Share.objects.get(shared_user_id=log_id)
which will return a single Share instance from which you can access the files_id attribute. An exception will be raised if the query would return anything other than 1 result.
If you want to get only the value from a single value QuerySet you can do:
file_s = Share.objects.filter(shared_user_id=log_id).values_list('files_id', flat=True).first()

How to convert a Django QuerySet to a list?

I have the following:
answers = Answer.objects.filter(id__in=[answer.id for answer in answer_set.answers.all()])
then later:
for i in range(len(answers)):
# iterate through all existing QuestionAnswer objects
for existing_question_answer in existing_question_answers:
# if an answer is already associated, remove it from the
# list of answers to save
if answers[i].id == existing_question_answer.answer.id:
answers.remove(answers[i]) # doesn't work
existing_question_answers.remove(existing_question_answer)
I get an error:
'QuerySet' object has no attribute 'remove'
I've tried all sorts to convert the QuerySet to a standard set or list. Nothing works.
How can I remove an item from the QuerySet so it doesn't delete it from the database, and doesn't return a new QuerySet (since it's in a loop that won't work)?
Why not just call list() on the Queryset?
answers_list = list(answers)
This will also evaluate the QuerySet/run the query. You can then remove/add from that list.
You could do this:
import itertools
ids = set(existing_answer.answer.id for existing_answer in existing_question_answers)
answers = itertools.ifilter(lambda x: x.id not in ids, answers)
Read when QuerySets are evaluated and note that it is not good to load the whole result into memory (e.g. via list()).
Reference: itertools.ifilter
Update with regard to the comment:
There are various ways to do this. One (which is probably not the best one in terms of memory and time) is to do exactly the same :
answer_ids = set(answer.id for answer in answers)
existing_question_answers = filter(lambda x: x.answer.id not in answers_id, existing_question_answers)
It is a little hard to follow what you are really trying to do. Your first statement looks like you may be fetching the same exact QuerySet of Answer objects twice. First via answer_set.answers.all() and then again via .filter(id__in=...). Double check in the shell and see if this will give you the list of answers you are looking for:
answers = answer_set.answers.all()
Once you have that cleaned up so it is a little easier for you (and others working on the code) to read you might want to look into .exclude() and the __in field lookup.
existing_question_answers = QuestionAnswer.objects.filter(...)
new_answers = answers.exclude(question_answer__in=existing_question_answers)
The above lookup might not sync up with your model definitions but it will probably get you close enough to finish the job yourself.
If you still need to get a list of id values then you want to play with .values_list(). In your case you will probably want to add the optional flat=True.
answers.values_list('id', flat=True)
By the use of slice operator with step parameter which would cause evaluation of the queryset and create a list.
list_of_answers = answers[::1]
or initially you could have done:
answers = Answer.objects.filter(id__in=[answer.id for answer in
answer_set.answers.all()])[::1]
You can directly convert using the list keyword.
For example:
obj=emp.objects.all()
list1=list(obj)
Using the above code you can directly convert a query set result into a list.
Here list is keyword and obj is result of query set and list1 is variable in that variable we are storing the converted result which in list.
Try this values_list('column_name', flat=True).
answers = Answer.objects.filter(id__in=[answer.id for answer in answer_set.answers.all()]).values_list('column_name', flat=True)
It will return you a list with specified column values
Use python list() function
list(). Force evaluation of a QuerySet by calling list() on it. For
example:
answers = list(answer_set.answers.all())
Why not just call
.values('reqColumn1','reqColumn2') or .values_list('reqColumn1','reqColumn2') on the queryset?
answers_list = models.objects.values('reqColumn1','reqColumn2')
result = [{'reqColumn1':value1,'reqColumn2':value2}]
OR
answers_list = models.objects.values_list('reqColumn1','reqColumn2')
result = [(value1,value2)]
You can able to do all the operation on this QuerySet, which you do for list .
def querySet_to_list(qs):
"""
this will return python list<dict>
"""
return [dict(q) for q in qs]
def get_answer_by_something(request):
ss = Answer.objects.filter(something).values()
querySet_to_list(ss) # python list return.(json-able)
this code convert django queryset to python list
instead of remove() you can use exclude() function to remove an object from the queryset.
it's syntax is similar to filter()
eg : -
qs = qs.exclude(id= 1)
in above code it removes all objects from qs with id '1'
additional info :-
filter() used to select specific objects but exclude() used to remove