Get a single value from user database django - python

im new on django, and i want to get a single value from a queryset, te query would be something like this:
select last_task from User where user_id=1
I tried with values() and only() but it doesnt work.
worker = request.user
Worker.objects.filter(user=worker.id).values("last_board")
values() return me a dictionary and i cant extract the single value from it to use.

You're probably looking for values_list, in particular with flat=True. https://docs.djangoproject.com/en/3.2/ref/models/querysets/#django.db.models.query.QuerySet.values_list
worker = request.user
Worker.objects.filter(user=worker.id).values_list("last_board", flat=True)
This will return a flat list of "last_board" values. If there is only one value, then it will return the single value. If there are multiple, it will return a list of values (no dict or unnecessary tuple).

Related

DRF: Designate number of entries for queryset using prefetch_related

In my view i am trying to use prefetch_related to get data from 2 related models. The following line gives me the results i want by returning the most recent entry for all controllers in my database
# allNames is a list containing all the names of controllers i want to get data for
measurements = Microcontrollers.objects.filter(name=allNames[i]).prefetch_related(Prefetch('measurements_basic',queryset=MeasurementsBasic.objects.order_by('-time_taken')))
However when i try to get more entries by adding [:3] at the end it still only returns one for each name in the list. When i try to do so on the prefetch query i get a slice error.
AssertionError at /api/CUTAQ/all/testdata/
Cannot filter a query once a slice has been taken.
My question is how i can make it so i get the amount of entries i want for each name in the list.
Slicing is not used for getting sets of data from a queryset consecutively. If that's what you need, you better go with paginating your queryset instead.

Django: Get one key and value from queryset dictionary

I have this query:
item = Item.objects.filter(id=3)
It is returning a queryset with its the keys and values.
Now I need to extract a particular value from the queryset, like this:
item_name = item['name']
But it does not work. How can I achieve this? Send the most simple way if possible, please. Thanks!
You have several wrong assumptions here.
A queryset is not a dict and does not have keys and values. It's a sequence of items, if anything most similar to a list.
I think what you want to do is to get a specific instance from the database, and access its fields. To get one instance you use get, not filter, as filter will always give you a queryset even if there is only a single match. Then, from that instance, you use attribute access not dict lookup. So:
item = Item.objects.get(id=3)
item_name = item.name
Here you can use the getattr function of python through which you can get your objective.
getattr(item, 'name')

Django - calling attribute from queryset with a string

I'm trying to loop over different query sets while not repeating myself too much and have encountered a problem using the queryset class.
This is not necessarily completely a Django-problem.
What I'm trying to do is to use my keylist, which corresponds to a django model's column names, to create a list of the data from those column names, what i want to do is something like this:
if needthisdata==1:
needdata=['column1', 'column2', 'column3']
else:
needdata=['column1', 'column4', 'column7']
entry=djangomodel.get.all().filter(identifier='id')
dictitems=[]
for n in range(0, len(needdata)):
if n==0:
dictitems=[entry.needdata[n]]
else:
dictitems.append(entry.needdata[n])
Which of course doesn't work since the queryset doesn't have a need data attribute, is there some way to call an attribute for a class with a string in this way?
A valid Django statement to obtain a single entry
First of all, there are some semantical problems here:
itentifier should probably be identifier, id, or pk;
you use .all immedately instead of first obtaining a manager (probably .objects); and
you here use a .filter(..) on the queryset to filter on an identifier, but usually this should be a .get(..), since by using a filter, zero, one or more results can be returned in an iterable.
entry = djangomodel.objects.get(id=some_id)
So now we obtain a single entry, but that of course does not resolve
obtaining the columns.
If all elements are real Django columns
In case the columns are real Django fields (so no #propertys, etc.) then we can use values_list, and perform a list(..) constructor on it:
dictitems = list(djangomodel.objects.values_list(*needdata).get(id=some_id))
If case some elements are #propertys
In case not all those fields are real Django fields, then we can use attrgetter instead:
from operator import attrgetter
dictitems = list(attrgetter(*needdata)(djangomodel.objects.get(id=some_id)))

Using 'like', '<=' and '=' operators when building an SQLAlchemy query filter from dict

I currently have a python dictionary that is created from the data that a user submits through a form. The form fields are optional, but if they are all filled out, then the dictionary (dict_filter) might look like this:
{"item_type": "keyboard", "location": "storage1"}
I can then query the database as shown:
items = Item.query.filter_by(**dict_filter).all()
This works fine and returns all the keyboard items that are currently in storage1 as desired.
However, I want to add two new date fields to the form such that a completely filled out form would result in a dictionary similar to the following:
{"item_type": "keyboard", "location": "storage1", "purchase_date": 2017-02-18, "next_maintenance": 2018-02-18}
Based on this new dict, I would like to do the following:
First, use like() when filtering the item_type. I want this so that if a user searches for keyboard then the results will also include items like mechanical keyboard for example. I know I can do this individually as shown:
val = form.item_type.data
items = Item.query.filter(getattr(Item, 'item_type').like("%%%s%%" % val)).all()
Second, use the '<=' (less than or equal to) operator when dealing with dates such that if, for example, a user enters a purchase_date in the form, then all the items returned will have a purchase_date before or on the same date as entered by the user. I know I can do this individually as shown:
items = Item.query.filter(Item.purchase_date <= form.purchase_date.data)
Note that if both dates are filled out in the form, then the filter should check both dates as shown:
items = Item.query.filter(and_(Item.purchase_date <= form.purchase_date.data, Item.next_maintenance <= form.next_maintenance.data))
Third, if the location field is filled out in the form, then the query should check for items with matching locations (as it currently does with the dict). I know I can do this using a dict as I am currently doing:
dict = {"location": "storage1"}
items = Item.query.filter_by(**dict_filter).all()
or
items = Item.query.filter_by(location=form.location.data).all()
The greatest challenge that I have is that since the form fields are optional I have no way of knowing beforehand what combination of filter conditions I'll have to apply. Therefore, it may be possible that for one user's input, I'll have to search the db for all screen items in office1 with next_maintenance date before yyyy-mm-dd while for another user's input I'll have to search the db for all items in all location regardless of next_maintenance date with a purchase_date before yyyy-mm-dd, and so on. This is precisely why I'm currently using a dict as a filter; it allows me to check if a form field was completed and if it was, then I add it to the dict and filter only based on form fields with input.
With all that being said, how can I combine all three filters discussed above (like, <=, =) into one while also accounting for the fact that not all three filters may always be necessary?
This was not intended to be an answer but a comment. But apparently I can't use code block in a comment.
In case you don't know, you can use multiple filter or filter_by by chaining them together like this:
Item.query.filter(Item.a < 5).filter(Item.b > 6).all()
Therefore you can store the returning value as a variable (it is actually an object of Query) temporarily and use it later.
q = Item.query.filter(Item.a < 5)
if some_condition_value:
q = q.filter(Item.b > 6)
items = q.all()
You can apply your conditions to the Query object and then you can have optional filters.

Django models - how to filter out duplicate values by PK after the fact?

I build a list of Django model objects by making several queries. Then I want to remove any duplicates, (all of these objects are of the same type with an auto_increment int PK), but I can't use set() because they aren't hashable.
Is there a quick and easy way to do this? I'm considering using a dict instead of a list with the id as the key.
In general it's better to combine all your queries into a single query if possible. Ie.
q = Model.objects.filter(Q(field1=f1)|Q(field2=f2))
instead of
q1 = Models.object.filter(field1=f1)
q2 = Models.object.filter(field2=f2)
If the first query is returning duplicated Models then use distinct()
q = Model.objects.filter(Q(field1=f1)|Q(field2=f2)).distinct()
If your query really is impossible to execute with a single command, then you'll have to resort to using a dict or other technique recommended in the other answers. It might be helpful if you posted the exact query on SO and we could see if it would be possible to combine into a single query. In my experience, most queries can be done with a single queryset.
Is there a quick and easy way to do this? I'm considering using a dict instead of a list with the id as the key.
That's exactly what I would do if you were locked into your current structure of making several queries. Then a simply dictionary.values() will return your list back.
If you have a little more flexibility, why not use Q objects? Instead of actually making the queries, store each query in a Q object and use a bitwise or ("|") to execute a single query. This will achieve your goal and save database hits.
Django Q objects
You can use a set if you add the __hash__ function to your model definition so that it returns the id (assuming this doesn't interfere with other hash behaviour you may have in your app):
class MyModel(models.Model):
def __hash__(self):
return self.pk
If the order doesn't matter, use a dict.
Remove "duplicates" depends on how you define "duplicated".
If you want EVERY column (except the PK) to match, that's a pain in the neck -- it's a lot of comparing.
If, on the other hand, you have some "natural key" column (or short set of columns) than you can easily query and remove these.
master = MyModel.objects.get( id=theMasterKey )
dups = MyModel.objects.filter( fld1=master.fld1, fld2=master.fld2 )
dups.all().delete()
If you can identify some shorter set of key fields for duplicate identification, this works pretty well.
Edit
If the model objects haven't been saved to the database yet, you can make a dictionary on a tuple of these keys.
unique = {}
...
key = (anObject.fld1,anObject.fld2)
if key not in unique:
unique[key]= anObject
I use this one:
dict(zip(map(lambda x: x.pk,items),items)).values()

Categories