I have a very simple query: select * from tbl1 where title not in('asdasd', 'asdasd').
How do I translate that to Django? It's like I want the opposite of: Table.objects.filter(title__in=myListOfTitles)
try using exclude
Table.objects.exclude(title__in=myListOfTitles)
(this thread is old but still could be googled)
you can use models.Q with "~" as follows:
Table.objects.filter(~Q(title__in=myListOfTitles))
this method specially is helpful when you have multiple conditions.
Table.objects.exclude(title__in=myListOfTitles)
Django provides two options.
exclude(<condition>)
filter(~Q(<condition>))
Method 2 using Q() method
>>> from django.db.models import Q
>>> queryset = User.objects.filter(~Q(id__lt=5))
Related
What is the correct way to do the following query:
sites = Site.objects.all().exclude(itempage__isnull=True or itempage__pk=1)
I would recommend using Django's Q Objects to construct more complex queries.
from django.db.models import Q
Site.objects.exclude(Q(itempage__isnull=True) | Q(itempage__pk=q))
Q objects also support negation with the ~ operator like so:
from django.db.models import Q
Site.objects.filter(~Q(Q(itempage__isnull=True) | Q(itempage__pk=q)))
Just wanted to another way of achieving this. Just chain the conditions using exclude().
sites = Site.objects.all().exclude(itempage__isnull=True).exclude(itempage__pk=1)
Is there a mechanism to map Django QuerySet items not triggering its evaluation?
I am wondering about something like Python map. A function that uses a function to apply it over the QuerySet, but keeping the lazy evaluation.
For example, using models from Django documentation example, is there something like? (not real code):
>>> Question.objects.all().map(lambda q: q.pub_date + timedelta(hours=1))
which keeps the lazy evaluation?
Just working through something like this myself. I think the best way to do it is to use a python list comprehension.
[q.pub_date + timedelta(hours=1) for q in Question.objects.all()]
Then Django takes care of optimizing this as it would any other query.
You can use annotate for this purpose, for example
from datetime import timedelta
from django.db.models import F, ExpressionWrapper, DateTimeField
Question.objects.annotate(
new_pub_date=ExpressionWrapper(
F('pub_date') + timedelta(hours=1),
output_field=DateTimeField()
)
)
For something a little bit more complex than this example, you can use Func, Case, When
You can use values_list to get any column you like:
Question.objects.values_list('pub_date')
This is simpler than anything you can cook up yourself.
I want to do pretty much the same like in this ticket at djangoproject.com, but with some additonal formatting. From this query
>>> MyModel.objects.values('cryptic_value_name')
[{'cryptic_value_name': 1}, {'cryptic_value_name': 2}]
I want to get something like that:
>>> MyModel.objects.values(renamed_value='cryptic_value_name')
[{'renamed_value': 1}, {'renamed_value': 2}]
Is there another, more builtin way or do I have to do this manually?
From django>=1.8 you can use annotate and F object
from django.db.models import F
MyModel.objects.annotate(renamed_value=F('cryptic_value_name')).values('renamed_value')
Also extra() is going to be deprecated, from the django docs:
This is an old API that we aim to deprecate at some point in the future. Use it only if you cannot express your query using other queryset methods. If you do need to use it, please file a ticket using the QuerySet.extra keyword with your use case (please check the list of existing tickets first) so that we can enhance the QuerySet API to allow removing extra(). We are no longer improving or fixing bugs for this method.
Without using any other manager method (tested on v3.0.4):
from django.db.models import F
MyModel.objects.values(renamed_value=F('cryptic_value_name'))
Excerpt from Django docs:
An F() object represents the value of a model field or annotated
column. It makes it possible to refer to model field values and
perform database operations using them without actually having to pull
them out of the database into Python memory.
It's a bit hacky, but you could use the extra method:
MyModel.objects.extra(
select={
'renamed_value': 'cryptic_value_name'
}
).values(
'renamed_value'
)
This basically does SELECT cryptic_value_name AS renamed_value in the SQL.
Another option, if you always want the renamed version but the db has the cryptic name, is to name your field with the new name but use db_column to refer to the original name in the db.
I am working with django 1.11.6
( And the key:value pair is opposite to that of accepted answer )
This is how i am making it work for my project
def json(university):
address = UniversityAddress.objects.filter(university=university)
address = address.extra(select={'city__state__country__name': 'country', 'city__state__name': 'state', 'city__name': 'city'})
address = address.values('country', 'state', "city", 'street', "postal_code").get()
return address
Note that adding simultanous objects.filter().extra().values() is same as above.
Try passing as kwargs:
MyModel.objects.annotate(**{'A B C':F('profile_id')}).values('A B C')
In my case, there were spaces and other special characters included in the key of each value in the result set so this did the trick.
Its more than simple if you want to rename few fields of the mode.
Try
projects = Project.objects.filter()
projects = [{'id': p.id, 'name': '%s (ID:%s)' % (p.department, p.id)} for p in projects]
Here i do not have a name field in the table, but i can get that after tweaking a little bit.
Is it possible to use AS sql statement with Django ORM:
SELECT my_field AS something_shiny WHERE my_condition = 1
If it is possible then how?
By now the Django documentation says that one should use extra as a last resort.
So here is a better way to do this query:
from django.db.models import F
Foo.objects.filter(cond=1).annotate(sth_shiny=F('my_field'))
use extra()
Foo.objects.filter(cond=1).extra(select={'sth_shiny':'my_field'})
Then you could access sth_shiny attr of resulted Foo instances
I've got an app where users create pages. I want to run a simple DB query that returns how many users have created more than 2 pages.
This is essentially what I want to do, but of course it's not the right method:
User.objects.select_related('page__gte=2').count()
What am I missing?
You should use aggregates.
from django.db.models import Count
User.objects.annotate(page_count=Count('page')).filter(page_count__gte=2).count()
In my case, I didn't use last .count() like the other answer and it also works nice.
from django.db.models import Count
User.objects.annotate( our_param=Count("all_comments")).filter(our_param__gt=12)
use aggregate() function with django.db.models methods!
this is so useful and not really crushing with other annotation aggregated columns.
*use aggregate() at the last step of calculation, it turns your queryset to dict.
below is my code snippet using them.
cnt = q.values("person__year_of_birth").filter(person__year_of_birth__lte=year_interval_10)\
.filter(person__year_of_birth__gt=year_interval_10-10)\
.annotate(group_cnt=Count("visit_occurrence_id")).aggregate(Sum("group_cnt"))