I want to extract some particular columns from django query
models.py
class table
id = models.IntegerField(primaryKey= True)
date = models.DatetimeField()
address = models.CharField(max_length=50)
city = models.CharField(max_length=20)
cityid = models.IntegerField(20)
This is what I am currently using for my query
obj = table.objects.filter(date__range(start,end)).values('id','date','address','city','date').annotate(count= Count('cityid')).order_by('date','-count')
I am hoping to have a SQL query that is similar to this
select DATE(date), id,address,city, COUNT(cityid) as count from table where date between "start" and "end" group by DATE(date), address,id, city order by DATE(date) ASC,count DESC;
At least in Django 1.10.5, you can use something like this, without extra and RawSQL:
from django.db.models.functions import Cast
from django.db.models.fields import DateField
table.objects.annotate(date_only=Cast('date', DateField()))
And for filtering, you can use date lookup (https://docs.djangoproject.com/en/1.11/ref/models/querysets/#date):
table.objects.filter(date__date__range=(start, end))
For the below case.
select DATE(date), id,address,city, COUNT(cityid) as count from table where date between "start" and "end" group by DATE(date), address,id, city order by DATE(date) ASC,count DESC;
You can use extra where you can implement DB functions.
Table.objects.filter(date__range(start,end)).extra(select={'date':'DATE(date)','count':'COUNT(cityid)'}).values('date','id','address_city').order_by('date')
Hope it will help you.
Thanks.
Related
I have a model:
class Product(models.Model):
name = models.CharField(max_length=100)
class Sales(models.Model):
product_id = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='products')
date = models.DateTimeField(null=True)
price = models.FloatField()
How do I return data as the following sql query (annotate sales with product name, group by product, day and month, and calculate sum of sales):
select p.name
, extract(day from date) as day
, extract(month from date) as month
, sum(s.price)
from timetracker.main_sales s
left join timetracker.main_product p on p.id = s.product_id_id
group by month, day, p.name;
Thanks,
If only ORM was as simple as sql... Spent several hours trying to figuring it out...
PS. Why when executing Sales.objects.raw(sql) with sql query above I get "Raw query must include the primary key"
You can annotate with:
from django.db.models import Sum
from django.db.models.functions import ExtractDay, ExtractMonth
Product.objects.values(
'name',
month=ExtractDay('products__date')
day=ExtractDay('products__date'),
).annotate(
total_price=Sum('products__price')
).order_by('name', 'month', 'day')
Note: Normally one does not add a suffix …_id to a ForeignKey field, since Django
will automatically add a "twin" field with an …_id suffix. Therefore it should
be product, instead of product_id.
Note: The related_name=… parameter [Django-doc]
is the name of the relation in reverse, so from the Product model to the Sales
model in this case. Therefore it (often) makes not much sense to name it the
same as the forward relation. You thus might want to consider renaming the products relation to sales.
I am trying to query datetime field in django like the following:
http://127.0.0.1:8000/mr-check/?cname=4&date=2021-09-13+00:09
and views:
cname = request.GET['cname']
date = request.GET['date']
# try:
items = MaterialRequest.objects.filter(owner=cname).filter(delivery_required_on=d)
models:
delivery_required_on = models.DateTimeField(default=datetime.now)
now obviously I don't have an exact instance with 2021-09-13+00:09 but I have instances for the same date, how do I query a datetime field with just date?
You can use the date field lookup. This casts the value as a date.
MaterialRequest.objects.filter(owner=cname).filter(delivery_required_on__date=d)
Also allows chaining additional field lookup, such as gte:
MaterialRequest.objects.filter(owner=cname).filter(delivery_required_on__date__gte=d)
My django model datetime field is string. In this case, how to get data between two dates?
models.py
class asdf(models.Model):
recordDate = models.CharField(max_length=20,blank=True)
Change the 'recordDate' to DateField and use the following query:
asdf.objects.filter(recordDate__gte='2019-03-01', recordDate__lte='2019-03-09')
In order to get between range use filter this query:
models.asdf.objects.filter(recordDate__gte='start_date', recordDate__lt='end_date')
start_date and end_date may be string in date formats or datetime parsed object.
This is working for me
remember one thing what you are storing in you db means only date or datetime
when datetime
start = '2021-08-12 21:52:33.118649'
end = '2021-08-13 06:30:46.909572'
user = UserAccount.objects.filter(created_at__gte=start,
created_at__lte=end)
print user
when date
start = '2021-08-12'
end = '2021-08-13'
user = UserAccount.objects.filter(created_at__gte=start,
created_at__lte=end)
print user
or you can filter by using __range here also
start = '2021-08-12 21:52:33.118649'
end = '2021-08-13 06:30:46.909572'
user = UserAccount.objects.filter(created_at__range=(start, end))
print user
if you you are storing in db datatime and you want to retrieve only date from db
from datetime import datetime
datetime.strptime('2014-12-04', '%Y-%m-%d').date()
I have the following relation:
class Product(foo):
name = models.CharField()
class Maintenance(foo):
product = models.ForeignKey(Product, related_name="maintenances")
start = models.DateField()
end = models.DateField()
I would like to filter all products with the latest (only the latest) maintenance object having start and end attributes in a given date range.
Something like this:
Product.objects.filter(maintenances__last__end__gte=today.now(), maintenances__last__end__lte=today.now()+datetime.timedelta(days=30))
You could filter the products on the selected range of dates for maintenances and then take the lastest maintenance using annotation on Max:
import datetime as dt
from django.db.models import Max
start_date = dt.datetime.now()
end_date = dt.datetime.now() + dt.timedelta(days=30)
products = Product.objects.filter(maintenances__start__gte=start_date, maintenances__end__lte=end_date)\
.annotate(most_recent_maint=Max('maintenances__id'))\
.prefetch_related('maintenances')
In some cases it also might make sense to think the other way round: Select the latest Maintenance object for every product:
# filter for time range
maintenances = Maintenance.objects.filter(
end__gte=today.now(),
end__lte=today.now() + datetime.timedelta(days=30)
)
# get latest with distinct product id
maintenances = maintenances.order_by(
'product_id', '-end'
).distinct('product_id')
# do a `select_related` to get all products in the same query
maintenances = maintenances.select_related('product')
Note that passing arguments to distinct() only works if you are using PostgreSQL.
If I have a Django Employee model with a start_date and end_date date field, how can I use get in the ORM to date effectively select the correct record if different versions of the record exist over time based on these date fields?
So I could have the following records:
start_date, end_date, emp
01/01/2013, 31/01/2013, Emp1
01/02/2013, 28/02/2013, Employee1
01/03/2013, 31/12/4000. EmpOne
And if today's date is 10/02/2013 then I would want Employee1.
Something similar to:
from django.utils import timezone
current_year = timezone.now().year
Employee.objects.get(end_date__year=current_year)
or
res = Employee.objects.filter(end_date__gt=datetime.now()).order_by('-start_date')
Or is there a more efficient way of doing the same?
Your second example looks fine. I corrected the filter parameters to match your start_date constraints. Also, i added a LIMIT 1 ([:1]) for better performance:
now = datetime.now()
employees = Employee.objects.filter(start_date__lt=now, end_date__gt=now).order_by('-start_date')
employee = employees[:1][0] if employees else None