Can I combine the use of filter() and get() on querysets to return an object in a django view?
I have the following view;
def my_view(request, city, store, item):
item = Item.objects.filter(store__city=city, city=city).get(item=item)
Items are all unique for city and store. I am currently trying to filter a queryset based on the two ForeignKey fields and then use get on a CharField but am getting an error message that the object does not exist. Am I approaching this incorrectly or is my syntax off somewhere? Thanks
If your related filter returns only 1 result, then you can use :
def my_view(request, city, store, item):
item = Item.objects.filter(store__city=city, city=city)[0]
which filters the Item records and store them in a QuerySet, which has a list-lilke structure, then take the first element...
If you are sure to get a result, then you can use get instead of filter:
item = Item.objects.get(store__city=city, city=city)
But if there exists no record which fits your filer criteria, then you get an error. So if you are not sure whether filtering will return a result or not, then use:
item = Item.objects.filter(store__city=city, city=city)
if item:
item = item[0]
which ckecks the resulting queryset and takes the first result if exists any.
Related
Is there a way to add object to aggregated queryset?
For example:
qs = Model.objects.filter(title="abc").aggregate(likes=Count('likes'))
and i want to do something like:
qs = Model.objects.filter(title="abc").aggregate(likes=Count('likes')).get(pk=1)
Whenever a queryset is evaluated, its results are cached. However, this cache does not carry over if you use another method, such as filter or order_by or get, on the queryset. SO you can't try to evaluate the bigger set, and use filtering on the queryset to retrieve the smaller sets without doing another query.
So you can go by doing it this way:
qs = Model.objects.filter(pk=1, title="abc")
if the qs is None you do not have data that matches the query to start with, if it is not None you can go and do it like this:
qs_agg = qs.aggregate(likes=Count('likes'))
qs here is the one that we got from the filtering
I wrote an action that is supposed update a field in every record selected by the user according to this document.
The problem is that queryset is always empty and thus, no changes take place.
def SendCommandAction(self, request, queryset):
print(self._Command)
commandStatus = {
'Command':self._Command,
'Fetched':False
}
print(queryset) #output from console: <QuerySet []>
updated = queryset.update(Command_Status = commandStatus,)
self.message_user(request, ngettext(
'%d record was successfully updated.',
'%d records were successfully updated.',
updated,
) % updated, messages.SUCCESS)
After I select records and hit "Go" button this message appeares:
0 records were successfully updated.
I'm having a similar issue and found that this method options.response_action is responsable for handling the action and the queryset it gets.
In my case, I'm using mongodb, and that method response_action is overwriting my queryset (the method is filtering by objects pks, but for mongodb you need to provide ObjectId instances to the filter function and django admin use just strings).
if not select_across:
# Perform the action only on the selected objects
queryset = queryset.filter(pk__in=selected)
# `selected` here is a list of strings (and for mongodb should be bson.ObjectId)
# that is the reason the queryset is empty in my case
I solved this creating a custom queryset class for my model and overwrite the filter function carefully to convert list of strings to list of bson.ObjectIDs only if the filter includes pk on it.
I think you need to debug this method and figure out what is happening in your case.
Good luck!
Luis.-
I'd like to find adjacent items in a queryset given a primary key, as asked here. However I want this to work for any given queryset, that i haven't set the ordering for myself. How can I find the current ordering of a queryset for __gt and __lt filtering?
For example:
queryset = MyModel.objects.all().order_by('some_field')
next_obj = get_next(queryset, after_pk, 10)
...
def get_next(queryset, pk, n):
#ordering is unknown here
obj = queryset.get(pk=pk)
field = queryset.get_order_by_field_name() #???
return queryset.filter(**{field+'__gt': getattr(obj, field)})[:n]
The model may define a default ordering and I can check if the queryset is ordered, but I don't think either are helpful in this case.
You can retrieve the list of columns from order_by clause by accessing queryset.query.order_by property.
From django docs:
The query attribute is an opaque object. It represents the internals of the query construction and is not part of the public API. However, it is safe (and fully supported) to pickle and unpickle the attribute’s contents as described here.
I have 3 separate models. I would like to be able to do a query on all tables and return the object with the latest date. What would be the best approach for this? I currently have them returned in a chain. All of the models contain an auto_now_add DateTimeField. Is it possible to filter the latest created object based on the chained queryset?
article_list = Article.objects.all()
issue_list = Issue.objects.all()
annual_list = Annual.objects.all()
result_list = list(chain(article_list, issue_list, annual_list))
if you want only 1 object you can use max() with key
max(result_list, key=lambda x: x.date) #or whatever the name of the field is (should be same on all models)
on the same fashion if you want the whole list sorted by the date field you can use sorted() and give the above key
Right now I have a Django queryset that I want to filter by the result of another query set. Right now I am doing this as (and it works):
field = 'content_object__pk'
values = other_queryset.values_list(field, flat=True)
objects = queryset.filter(pk__in=values)
where the field is the name of a foreign key the pk in queryset. The ORM is smart enough to run the above is one query.
I was trying to simplify this to (ie to filter with the object list themselves rather than having to explicitly say pk):
field = 'content_object'
objects = queryset & other_queryset.values_list(field, flat=True)
but this gives the following error:
AssertionError: Cannot combine queries on two different base models.
What is the right way to do this type of filtering?
You can do the next:
result = MyModel.objects.filter(field__in=other_query)
The results will be the objects in the model where the field is a foreign key to the model in the other_query
you can chain queries in Django...
qs = entry.objects.filter(...).filter(...)