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

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

Related

Problem with .only() method, passing to Pagination / Serialization --- all fields are getting returned instead of the ones specified in only()

I am trying load some data into datatables. I am trying to specify columns in the model.objects query by using .only() --- at first glance at the resulting QuerySet, it does in fact look like the mySQL query is only asking for those columns.
However, When I try to pass the QuerySet into Paginator, and/or a Serializer, the result has ALL columns in it.
I cannot use .values_list() because that does not return the nested objects that I need to have serialized as part of my specific column ask. I am not sure what is happening to my .only()
db_result_object = model.objects.prefetch_related().filter(qs).order_by(asc+sort_by).only(*columns_to_return)
paginated_results = Paginator(db_result_object,results_per_page)
serialized_results = serializer(paginated_results.object_list,many=True)
paginated_results.object_list = serialized_results.data
return paginated_results
This one has tripped me up too. In Django, calling only() doesn't return data equivalent to a SQL statement like this:
SELECT col_to_return_1, ... col_to_return_n
FROM appname_model
The reason it doesn't do it like this is because Django returns data to you not when you construct the QuerySet, but when you first access data from that QuerySet (see lazy QuerySets).
In the case of only() (a specific example of what is called a deferred field) you still get all of the fields like you normally would, but the difference is that it isn't completely loaded in from the database immediately. When you access the data, it will only load the fields included in the only statement. Some useful docs here.
My recommendation would be to write your Serializer so that it is only taking care of the one specific filed, likely using a SerializerMethodField with another serializer to serialize your related fields.

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 could django model get one field?

I know how to get a line,but I don't know how to get one field.
for exmple,there is a table,have id,title,content fields.
ModelsExample.objects.filter(id = showid)# get one line.
how to get title field only?
You can use values or values_list for that matter. Depending on how you would like to use tour context:
Use of values() example:
r = ModelsExample.objects.filter(id=showid).values('title')
This would return something like: [{'title': 'My title'}] so you could access it with r[0]['title'].
Use of values_list() example:
r = ModelsExample.objects.filter(id=showid).values_list('title')
This would return something like: [('My title',)] so you could access it as r[0][0].
Use of values_list(flat=True) example:
r = ModelsExample.objects.filter(id=showid).values_list('title', flat=True)
This would return something like: ['My title'] so you could access it as r[0].
And of course you can always access each field of the model as:
r = ModelsExample.objects.get(id=showid)
r.title
You can get only one field like this
ModelsExample.objects.filter(id = showid).values('title')
https://docs.djangoproject.com/en/1.8/ref/models/querysets/#values
You have two ways:
ModelsExample.objects.filter(id=showid)[0].title
ModelsExample.objects.filter(id=showid).only('title')[0].title
or
ModelsExample.objects.get(id=showid).title
First fetch collection and get first element. If collection don't have elements they raise IndexError.
Second get one element. If in DB You have more elements they raise MultipleObjectsReturned. If cannot found any row, they raise NoResultFound.

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