On o postgresql db based Django, how can I filter by time for a datetimefield as below?
class Foo(models.Model):
start_date = models.DateTimeField()
end_date = models.DateTimeField()
IE: I want to filter Foo objects with "16:30" start_date and "19:00" end_date.
Thanks.
What about adding in a TimeField?
http://docs.djangoproject.com/en/dev/ref/models/fields/#timefield
Otherwise you would need to write a custom query to take advantage of the databaseĀ“s time capabilites since DateTimeFields don't have that capability natively in Django.
You could consider writing a function to denormalize hours and minutes from start_date to a new start_time field and then query the start_time field.
Solution to my own q:
def query_by_times(start_hour, start_min, end_hour, end_min):
query = 'EXTRACT(hour from start_date) = %i and EXTRACT(minute from start_date) = %i and EXTRACT(hour from end_date) = %i and EXTRACT(minute from end_date) = %i' % (start_hour, start_min, end_hour, end_min)
return Foo.objects.extra(where=[query])
In your situation, database normalization looks like thebest solution, since execution time and system load will rise as your related database table keeps more records...
Another solution to do this without using database filer functions is using filter alongside lambda:
from datetime import time
records = Foo.objects.all()
filtered = filter(lambda x: (time(16,30)==x.start_date.time() and time(19,0)==x.end_date.time()), records)
But using this on a large dataset will need too much time and system resource.
Try
Foo.objects.filter(start_date = MyDate1, end_date = MyDate2)
where MyDate1 and MyDate2 are your defined datetime objects. It should work, right?
I think which you need uses the range[1].
[1]http://docs.djangoproject.com/en/1.2/ref/models/querysets/#range
Related
According to this document that was added on v1.9 we can able to query a DateTimeField by date without time.
Examples are:
Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
But it is not working for me:
class MilkStorage(models.Model):
....
created_at = models.DateTimeField(null=False)
Usage
from datetime import date
MilkStorage.objects.filter(created_at__date=date.today())
It returns an empty queryset <QuerySet []>.
Does this query only works on PostgreSQL? im using MySQL.
Depending on your specific requirements, this may or may not be an ideal solution. I found that __date works if you set USE_TZ = False in settings.py
I had this same problem (I couldn't even filter by __month or __day) until I disabled USE_TZ. Again, may not be ideal for your case, but it should get __date working again.
I have a visitor model. In this model I filtered data through date not time and it's working.
models.py
Visitor(models.Model):
timestamp = models.DateTimeField(_('Login Date Time'), auto_now=True)
os_info = models.CharField(_('OS Information'), max_length=30, null=True)
views.py
import datetime
visitor = Visitor.objects.filter( timestamp__lte=datetime.datetime.now().date())
print visitor
Output:
<Visitor: Windows 10>, <Visitor: Windows 10>]
Use above way to filter data from date.
If you are using a MYSQL database, you may need to do the following:
Load the time zone tables with mysql_tzinfo_to_sql https://dev.mysql.com/doc/refman/8.0/en/mysql-tzinfo-to-sql.html
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
I have an application where users select their own display columns. Each display column has a specified formula. To compute that formula, I need to join few related columns (one-to-one relationship) and compute the value.
The models are like (this is just an example model, actual has more than 100 fields):
class CompanyCode(models.Model):
"""Various Company Codes"""
nse_code = models.CharField(max_length=20)
bse_code = models.CharField(max_length=20)
isin_code = models.CharField(max_length=20)
class Quarter(models.Model):
"""Company Quarterly Result Figures"""
company_code = models.OneToOneField(CompanyCode)
sales_now = models.IntegerField()
sales_previous = models.IntegerField()
I tried doing:
ratios = {'growth':'quarter__sales_now / quarter__sales_previous'}
CompanyCode.objects.extra(select=ratios)
# raises "Unknown column 'quarter__sales_now' in 'field list'"
I also tried using raw query:
query = ','.join(['round((%s),2) AS %s' % (formula, ratio_name)
for ratio_name, formula in ratios.iteritems()])
companies = CompanyCode.objects.raw("""
SELECT `backend_companycode`.`id`, %s
FROM `backend_companycode`
INNER JOIN `backend_quarter` ON ( `backend_companycode`.`id` = `backend_companyquarter`.`company_code_id` )
""", [query])
#This just gives empty result
So please give me a little clue as to how I can use related columns preferably using 'extra' command. Thanks.
By now the Django documentation says that one should use extra as a last resort.
So here is a query without extra():
from django.db.models import F
CompanyCode.objects.annotate(
growth=F('quarter__sales_now') / F('quarter__sales_previous'),
)
Since the calculation is being done on a single Quarter instance, where's the need to do it in the SELECT? You could just define a ratio method/property on the Quarter model:
#property
def quarter(self):
return self.sales_now / self.sales_previous
and call it where necessary
Ok, I found it out. In above using:
CompanyCode.objects.select_related('quarter').extra(select=ratios)
solved the problem.
Basically, to access any related model data through 'extra', we just need to ensure that that model is joined in our query. Using select_related, the query automatically joins the mentioned models.
Thanks :).
I need to find data within a certain set of parameters
I am building a small booking system, that lets user see what vehicles are available for booking for their little safari trip.
The system has bookings that have been entered previously or made previously by a client.
If a booking's pickup_date = 2011-03-01 and dropoff_date = 2011-03-15 and I run a query with pickup=2011-03-09 and dropoff=2011-03-14 in my views as below, it doesn't return any results to see if a booking within that timeframe has been made.
views.py
def dates(request, template_name='groups/_dates.html'):
pickup=request.GET.get('pickup','None');
dropoff=request.GET.get('dropoff','None');
order = Order.objects.filter(pick_up__lte=pickup).filter(drop_off__gte=dropoff)
context = {'order':order,}
return render_to_response(template_name,context,
context_instance=RequestContext(request))
Any suggestions on how to do this?
Or should I be looking at an alternate way of running this query?
Could it be posible that as your passing the raw string to the queryset is not on the correct format, try converting the strings to datetime objects.
Later you can try using the range lookup is more efficient on some DB engines and more simple to read and code.
from django.db.models import Q
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
orders = Order.objects.filter(drop_off__gte=start_date, pick_up__lte=end_date)
# Or maybe better
orders = Order.objects.filter(Q(drop_off__gte=start_date), Q(pick_up__lte=end_date))
Can you try this :
order = Order.objects.filter(pick_up**__date__**lte=pickup).filter(drop_off**__date__**gte=dropoff)
https://docs.djangoproject.com/fr/2.0/ref/models/querysets/#date