I have a queryset in my django view.
I would like to change the position of one of the item in order it to be the first element of the queryset.
Any idea on how to do that?
EDIT:
I have a queryset:
qs = UserProfile.objects.filter(myfilter=whatever)
I know that inside this queryset I have:
specific_user.userprofile
What I want to do is to put the user.userprofile in first position into my queryset because I use this queryset in a loop in my template:
{% for i in qs %}
<div> i.name </div>
And I want to be sure that the first name of the list is the name of the specific_user.
QuerySet objects in Django are abstract representations of the result of database queries. Generally speaking, it represents SQL that might later be executed when specific objects from the queryset are requested, but until that happens, no queries are executed. So you can't really think of a queryset like a list, which might be arbitrarily reordered. You can request the objects in your queryset to be sorted using its order_by method, so if you want a particular object to come first, it must have some sortable attribute on the DB side of things by which it can be ordered. This could be a column or a value calculated from its columns using F expressions.
But, for your needs, it seems like you could just make a list of your queryset in your view:
profiles = [specific_user.userprofile] + [profile for profile in UserProfile.objects.filter(myfilter=whatever).exclude(id=specific_user.userprofile.id)]
Add that to your context and iterate over it instead of the original queryset in your template.
Since Django 1.8 you have Conditional Expressions which you can use to define a specific order.
You would set a special case when the UserProfile is specific_user.userprofile:
qs = UserProfile.objects.filter(myfilter=whatever)\
.order_by(Case(When(pk=specific_user.userprofile.pk, then=0), default=1)))
We set the value of 0 in the special case, and 1 as default.
This way the specified user would always show first.
Related
This is how I have initialized an Empty Queryset now I want to add objects to it.
How can I do that.
from django.db.models.query import EmptyQuerySet
EmptyQuerySet is a class to checking if a queryset is empty by .none()
A queryset represents a query you make to your database and it have to be translatable to an SQL query.
So you can't add objects to a QuerySet like to python list but you can combine queryset using set operations.
See QuerySet API Reference for more information.
Specifically, I am looking to get a query of users. My User model has a first_name and last_name field. What I need to do is order the request.user at the top of the results, and the remaining users in alphabetical order by last_name, first_name. The last part is easy:
q = User.objects.all().order_by('last_name', 'first_name')
However I am not sure how to ensure that the request.user is the first result in the query. This is all being done for a django rest framework view, and thus (I believe) I need to have it done through a query which is passed on to the serializer.
First, it might be better design to not do this. Have some other endpoint that returns your own user object if you need it, and in the list view treat yourself no differently. But if you really neeed to.
You probably could use an annotation.
User.objects.annotate(is_me=Case(
When(pk=request.user.pk, then=Value(True)),
When(pk__ne=request.user.pk, then=Value(False)),
output_field=BooleanField())
).order_by('-is_me')
If you don't really need the result to be a queryset you can try the following:
import itertools
me = request.user
others = User.objects.exclude(id=me.pk)
users_list = itertools.chain([me], others)
A have piece of code, which fetches some QuerySet from DB and then appends new calculated field to every object in the Query Set. It's not an option to add this field via annotation (because it's legacy and because this calculation based on another already pre-fetched data).
Like this:
from django.db import models
class Human(models.Model):
name = models.CharField()
surname = models.CharField()
def calculate_new_field(s):
return len(s.name)*42
people = Human.objects.filter(id__in=[1,2,3,4,5])
for s in people:
s.new_column = calculate_new_field(s)
# people.somehow_reorder(new_order_by=new_column)
So now all people in QuerySet have a new column. And I want order these objects by new_column field. order_by() will not work obviously, since it is a database option. I understand thatI can pass them as a sorted list, but there is a lot of templates and other logic, which expect from this object QuerySet-like inteface with it's methods and so on.
So question is: is there some not very bad and dirty way to reorder existing QuerySet by dinamically added field or create new QuerySet-like object with this data? I believe I'm not the only one who faced this problem and it's already solved with django. But I can't find anything (except for adding third-party libs, and this is not an option too).
Conceptually, the QuerySet is not a list of results, but the "instructions to get those results". It's lazily evaluated and also cached. The internal attribute of the QuerySet that keeps the cached results is qs._result_cache
So, the for s in people sentence is forcing the evaluation of the query and caching the results.
You could, after that, sort the results by doing:
people._result_cache.sort(key=attrgetter('new_column'))
But, after evaluating a QuerySet, it makes little sense (in my opinion) to keep the QuerySet interface, as many of the operations will cause a reevaluation of the query. From this point on you should be dealing with a list of Models
Can you try it functions.Length:
from django.db.models.functions import Length
qs = Human.objects.filter(id__in=[1,2,3,4,5])
qs.annotate(reorder=Length('name') * 42).order_by('reorder')
I’ve written a search function for my django app which does a number of different filtering depending on the search string entered in the search box. I save the result of these different query filtering in a variable called ‘results’ (seems appropriate), but I am having trouble getting the template to render the variable properly depending on the type of object the queryset is based on. The results variable can either take the form of a queryset of ‘filtered’ object1 or 0 results (if nothing of object1 matched that search) OR it can take the form of a queryset of 'filtered' object2 or 0 results (if nothing of object2 matched that search). Later this might become many more different objects/models understandably so I would like to know how to check what type of object the queryset is composed of.
Any help would be really appreciated.
Given a Django queryset, you can retrieve its model using the well named model attribute, that gives a Model object.
queryset = SomeModel.objects
print queryset.model # prints 'path.to.your.app.models.SomeModel'
You probably do not want to check against the full path, so you can use __name__
print queryset.model.__name__ # prints 'SomeModel'
But since you cannot access underscore attributes in templates, you'll have to add this information in your view.
Update:
To check what is the model name in the template, you can add it on the queryset object:
queryset.model_name = queryset.model.__name__
Then in your template:
{% if queryset.model_name = 'SomeModel' %}
... do something
{% elif queryset.model_name = 'SomeOtherModel' %}
....
{% endif %}
1) Checking for a zero
2) checking for the field ".name" of the first element of selection.
also get class name for empty queryset in django - class - name - for - empty - queryset - in - django
If did not turn out, please code
Is there any way to specify a Django Queryset, which will do nothing but still be valid Queryset? Empty queryset should ideally not call DB and results would be empty.
Model.objects.none() always gives you an empty queryset
Use MyModel.objects.none() which will return an EmptyQuerySet, which is a QuerySet subclass that always evaluates to an empty list.
For eg., if you have a model class Entry (or just use models.Model), you can simply create an EmptyQuerySet by:
>>> Entry.objects.none()
[]