I'm using following code set to pull data from specific columns of the table...
cityList = City.objects.using(settings.DATABASE_CONF).filter(
status=1).values('city_name_en', 'city_id')
How can I set an alias for the city_name_en column? I have two other columns with city_name_fr city_name_de but the client can understand only city_name.
You can annotate the fields as you want, with the F expression:
from django.db.models import F
cityList = City.objects.using(settings.DATABASE_CONF).filter(status=1).values(
'city_name_en', 'city_id')
# use F expression to annotate with an alias
cityList = cityList.annotate(cityname=F('city_name_en'))
I think giving alias in Django query is not possible. However you can refer to this answer.
Related
I have a scenario that, i want a greatest value with the field name. I can get greatest value using Greatest db function which django provides. but i am not able to get its field name. for example:
emps = Employee.objects.annotate(my_max_value=Greatest('date_time_field_1', 'date_time_field_1'))
for e in emps:
print(e.my_max_value)
here i will get the value using e.my_max_value but i am unable to find out the field name of that value
You have to annotate a Conditional Expression using Case() and When().
from django.db.models import F, Case, When
emps = Employee.objects.annotate(
greatest_field=Case(
When(datetime_field_1__gt=F("datetime_field_2"),
then="datetime_field_1"),
When(datetime_field_2__gt=F("datetime_field_1"),
then="datetime_field_2"),
default="equal",
)
)
for e in emps:
print(e.greatest_field)
If you want the database query to tell you which of the fields was larger, you'll need to add another annotated column, using case/when logic to return one field name or the other. (See https://docs.djangoproject.com/en/4.0/ref/models/conditional-expressions/#when)
Unless you're really trying to offload work onto the database, it'll be much simpler to do the comparison work in Python.
I like to perform a Django query like the one below:
query = Dbmodel.objects.all().annotate(result=F('fieldname1') + F('fieldname2') + F('fieldname4'))
But instead of using the fieldnames directly, I would like to use a list with the field names:
fields = ['fieldname1', 'fieldname2', 'fieldname4']
Depending on user interaction the number of fieldnames in the list can variate. Is there a way to do it?
As this is my first question on StackOverflow, please let me know, if my question is unclear or I could improve my question.
You can do this by using operator.add to combine the multiple F expressions into a single expression, and pass that into the annotation.
It would look like this:
import operator
from django.db.models import F
# any amount of fields
fields = ["fieldname1", "fieldname2", "fieldname3"]
# combine into a single sum
combined_expression = reduce(operator.add, (F(x) for x in fields))
# the new query
query = Dbmodel.objects.all().annotate(result=combined_expression)
I have a simple query with filter and exclude. Exclude for Q & Q not working.
Below is the query that I am using.
start_date = (datetime(time.localtime().tm_year, time.localtime().tm_mon, 1) - timedelta(1)).replace(day=1)
data = models.Test.objects.filter(
is_deleted=False).exclude(Q(status__in=[1,2,3]) & Q(modified_at__lt=start_date))\
.select_related('created_by')\
.prefetch_related('name')
I want the exclude to work. If I use exclude twice, I'm getting the result.
From the doc
exclude(**kwargs)
Returns a new QuerySet containing objects that do not match the given lookup parameters.
The lookup parameters (**kwargs) should be in the format described in Field lookups below. Multiple parameters are joined via AND in the underlying SQL statement, and the whole thing is enclosed in a NOT().
So, just use Q() objects with comma seperation,
.exclude(Q(status__in=[1,2,3],Q(modified_at__lt=start_date))
I have a query that I can do with raw sql but am trying to convert it to use the Django ORM. The query is:
SELECT a.journey_pattern_ref_id
FROM(
SELECT * FROM journeypatterntiminglink
WHERE from_stop_id = '0180BAC30249'
) a,
journeypatterntiminglink b
WHERE a.journey_pattern_ref_id = b.journey_pattern_ref_id
AND b.to_stop_id = '0180BAC30035'
AND b.to_seq_no > a.from_seq_no;
The part that is giving me trouble is b.to_seq_no > a.from_seq_no. So far I have
jps = (JourneyPattern.objects
.filter(journeypatterntiminglink__from_stop=origin)
.filter(journeypatterntiminglink__to_stop=destination))
Well, you should use F() expressions to reference other fields in query construction rather than constants.
Inferring the definition of your model from your question it should be something like this:
from django.db.models import F
jps = (JourneyPattern.objects
.filter(journeypatterntiminglink__from_stop=origin)
.filter(journeypatterntiminglink__to_stop=destination)
.filter(journeypatterntiminglink__to_seq_no__gt=F('journeypatterntiminglink__from_seq_no'))
I have first_name, last_name & alias (optional) which I need to search for. So, I need a query to give me all the names that have an alias set.
Only if I could do:
Name.objects.filter(alias!="")
So, what is the equivalent to the above?
You could do this:
Name.objects.exclude(alias__isnull=True)
If you need to exclude null values and empty strings, the preferred way to do so is to chain together the conditions like so:
Name.objects.exclude(alias__isnull=True).exclude(alias__exact='')
Chaining these methods together basically checks each condition independently: in the above example, we exclude rows where alias is either null or an empty string, so you get all Name objects that have a not-null, not-empty alias field. The generated SQL would look something like:
SELECT * FROM Name WHERE alias IS NOT NULL AND alias != ""
You can also pass multiple arguments to a single call to exclude, which would ensure that only objects that meet every condition get excluded:
Name.objects.exclude(some_field=True, other_field=True)
Here, rows in which some_field and other_field are true get excluded, so we get all rows where both fields are not true. The generated SQL code would look a little like this:
SELECT * FROM Name WHERE NOT (some_field = TRUE AND other_field = TRUE)
Alternatively, if your logic is more complex than that, you could use Django's Q objects:
from django.db.models import Q
Name.objects.exclude(Q(alias__isnull=True) | Q(alias__exact=''))
For more info see this page and this page in the Django docs.
As an aside: My SQL examples are just an analogy--the actual generated SQL code will probably look different. You'll get a deeper understanding of how Django queries work by actually looking at the SQL they generate.
Name.objects.filter(alias__gt='',alias__isnull=False)
Firstly, the Django docs strongly recommend not using NULL values for string-based fields such as CharField or TextField. Read the documentation for the explanation:
https://docs.djangoproject.com/en/dev/ref/models/fields/#null
Solution:
You can also chain together methods on QuerySets, I think. Try this:
Name.objects.exclude(alias__isnull=True).exclude(alias="")
That should give you the set you're looking for.
1. When using exclude, keep the following in mind to avoid common mistakes:
Should not add multiple conditions into an exclude() block like filter(). To exclude multiple conditions, you should use multiple exclude().
Example: (NOT a AND NOT b)
Entry.objects.exclude(title='').exclude(headline='')
equal to
SELECT... WHERE NOT title = '' AND NOT headline = ''
======================================================
2. Only use multiple when you really know about it:
Example: NOT (a AND b)
Entry.objects.exclude(title='', headline='')
equal to
SELECT.. WHERE NOT (title = '' AND headline = '')
If you want to exclude null (None), empty string (""), as well as a string containing white spaces (" "), you can use the __regex along with __isnull filter option
Name.objects.filter(
alias__isnull = False,
alias__regex = r"\S+"
)
alias__isnull=False excludes all the columns null columns
aliax__regex = r"\S+" makes sure that the column value contains at least one or more non whitespace characters.
From Django 1.8,
from django.db.models.functions import Length
Name.objects.annotate(alias_length=Length('alias')).filter(alias_length__gt=0)
You can simply do this:
Name.objects.exclude(alias="").exclude(alias=None)
It's really just that simple. filter is used to match and exclude is to match everything but what it specifies. This would evaluate into SQL as NOT alias='' AND alias IS NOT NULL.
Another approach using a generic isempty lookup, that can be used with any field.
It can also be used by django rest_framework or other apps that use django lookups:
from distutils.util import strtobool
from django.db.models import Field
from django.db.models.lookups import BuiltinLookup
#Field.register_lookup
class IsEmpty(BuiltinLookup):
lookup_name = 'isempty'
prepare_rhs = False
def as_sql(self, compiler, connection):
sql, params = compiler.compile(self.lhs)
condition = self.rhs if isinstance(self.rhs, bool) else bool(strtobool(self.rhs))
if condition:
return "%s IS NULL or %s = ''" % (sql, sql), params
else:
return "%s <> ''" % sql, params
You can then use it like this:
Name.objects.filter(alias__isempty=False)
this is another simple way to do it .
Name.objects.exclude(alias=None)