converting NDB Datetimeproperty to date - python

I have a NDB datetime property stored on Google App Engine. I'm trying to query for all records since yesterday by converting the datetime to a date, then filtering the query for anything greater or equal to yesterdays date. However, I am getting the following error:
follower_trans = fol.query(
datetime.datetime.date(fol.followed_date) >= self.yesterday).fetch()
TypeError: descriptor 'date' requires a 'datetime.datetime' object but received a 'DateTimeProperty'
If i use just datetime.date() it sends an error requiring an integer as an argument.

You can't do a conversion as part of the query, so you'll have to create 'yesterday' as a datetime and filter using that.

fol.followed_date is the model's property, not an entity's value. You cannot convert a property to a date, as it has no value. You need to fix the query constructor:
follower_trans = fol.query(fol.followed_date >= self.yesterday).fetch()
(assuming you've created self.yesterday as a datetime object.)
Also, it is proper to use a capital letter for any Class names. Should have been:
class Fol(ndb.Model):
followed_date = ndb.DateTimeProperty(auto_now_add = True)
and
Fol.query(Fol.followed_date >= self.yesterday).fetch()

Related

Group By using Timestamp in Django Queryset

I have one model where each entry is stored and its created time is stored. The time is not a datetime object a timestamp. Timestamp field of model is shown below :
logged_at = models.CharField(_('log time'), max_length=128,
default=time.time)
If above field is datetime field then I can write an query which can group by records using datetime field like :
MyModel.objects.filter(type_='in').annotate(in_time=RawSQL('(date(logged_at))', [])).values('in_time', 'name').annotate(count=Count('name'))
But I am not able to query the timesatmp field in same way , It gives me the error date/time field value out of range
I have also tried to use functions like to_timestamp nut still no success
MyModel.objects.filter(type_='in').annotate(in_time=RawSQL('(date(to_timestamp(logged_at)))', [])).values('in_time', 'name').annotate(count=Count('name'))
Error : function to_timestamp(character varying) does not exist
Database I am using is Postgres
As #Willem mentioned in comment that timestamp must not be stored in CharField. So We can try to change type of field at runtime like given below.
MyModel.objects.filter(type_='in').annotate(in_time=RawSQL('(date(to_timestamp(logged_at::float)))', [])).values('in_time', 'name').annotate(count=Count('name'))
IN above query I have changed type of logged_at to float and it works fine for me, you can also change it to int.

use __gte for string date django

Date is in string format in database
class A(models.Model):
date = models.CharField(max_length=50, blank=True, null=True)
Yah i know it should be date type.
but now we have many records and we will soon change it to date type.
For current status i want get the objects greater than particular date.
So how can i use date__gte
example
objs = A.objects.filter(date__gte=datetime.now())
Is there any way to achieve this without converting date to datetime field.
I am not sure if that works. What you can try is a custom manager. So you can create a manager for your model, add something like date_gte and then convert the string to a datetime. Then you can user those operators as usual. That's a quick fix for now, but the best solution is to use a DateTimeField, which you want to do as far as I understood.
Example Manager:
from django.db import models
class MyManager(models.Manager):
def date_gte(self, date=datetime.now()):
items = []
for obj in self.all():
if datetime(obj.date) < date:
items.append(obj)
return items
Then you could call it like MyModel.objects.date_gte(date=datetime.now()).
Note: This is an expensive query and you may need to convert the simple list into QuerySet object. I haven't tested it, so this example should only help you get started.
There is no way to do this without a conversion (either in Django or the database during the query) to a proper DateTime type. You're trying to compare a datetime.datetime to a str. That won't work in normal Python and it won't work here.
What kind of string? if it is formatted to %Y%m%d, you can use .extra() method to do the query.
A.objects.extra(where=['date >= date_of_today'])

How do I query for objects created before a certain hour in a day in Django?

In Django, I am trying to filter my query only to objects that were created before a certain hour in the day. I have a datetime field called 'created_at' that stored the datetime from which that object was created.
What I would like to do is:
query = query.filter(created_at__hour__lte=10)
Which I would expect to get all the objects that were created before 10am. However, when I try that I get a:
FieldError: Join on field 'created_at' not permitted. Did you misspell 'hour' for the lookup type?
I could loop through each day and get that day's objects, but that seems highly inefficient. Is there a way I can do this in a single query? If not, what is the fastest way to run this sort of filter?
__hour on a DateTimeField is a lookup type, so you can't mix it with another lookup type like __lte. You could construct a filter with Q objects, EG:
before_ten = Q(created_at__hour=0)
for hour in range(1, 11):
before_ten = before_ten | Q(created_at__hour=hour)
query = query.filter(before_ten)
If you can change your data model, it might be more convenient to save a creation time TimeField as well as your existing created_at.
In Django 1.9+, you can chain hour lookups like created_at__hour__lte, so the query from the question will work.
query = query.filter(created_at__hour__lte=10)
import datetime
start_time = datetime.datetime.now().replace(hour=00, minute=00)
certain_hour = 10
end_time = start_time.replace(hour=certain_hour)
query = query.filter(created_at__range=(start_time, end_time)

How do I get each distinct 'year' value out of a Django model with a datetime field?

I can successfully filter by a given year in my Django model, but I'm having trouble finding a way to list valid years so a user can access them.
I have a django model with a defined 'datetime' field, oh-so-originally named 'date'. In my templates, I can successfully access the 'bar.date.date.year' field, so I know it exists, but when I try the following function...
blog_years=[]
for entry in blog_entries:
if entry.date.date.year not in blog_years:
blog_years.append(entry.date.date.year)
I'm told that "'builtin_function_or_method' object has no attribute 'year'"
I can only assume I"m tripping over some aspect of Python I'm not familiar with, but I can't figure out what it is. I'm quite certain it has to be syntactical, but past that...
Django has an elegant and efficient way of doing this. You can check from their docs https://docs.djangoproject.com/en/3.0/ref/models/querysets/#dates
But to go over it
Entry.objects.dates('pub_date', 'year')
This will bring out distinct year values in the query.
if you are using postgres, you can do
BlogEntry.objects.extra(select={"year": "EXTRACT(YEAR FROM date)"}).distinct().values_list("year", flat=True)
A Python set does not allow duplicates, so if you wanted a list of distinct years:
blog_years = list(set([entry.date.year for entry in blog_entries]))
Or, you could use distinct():
blog_years = blog_entries.distinct(entry__date__year).values(entry__date__year)
Of course, adjust the above based on your model.
The first .date accesses a datetime object.
The second .date is accessing a method on datetime objects that returns a date object but not calling it (this step is unneccessary).
The last part (the way you wrote it) is trying to access the year attribute of the date method, instead of accessing the year attribute of the result of the date method call.
Correcting the code to see the difference, it would look like this...
blog_years=[]
for entry in blog_entries:
if entry.date.date().year not in blog_years:
blog_years.append(entry.date.date().year)
But what you should do is more like this...
blog_years=[]
for entry in blog_entries:
if entry.date.year not in blog_years:
blog_years.append(entry.date.year)
since datetime objects have the date attribute as well.
date() is a method of datetime, use
blog_years=[]
for entry in blog_entries:
if entry.date.date().year not in blog_years:
blog_years.append(entry.date.date().year)
from django 1.10 it has become very simple
from django.db.models.functions import ExtractYear
blog_years= blog_entries.annotate(
year=ExtractYear('created_on')
).values_list('year', flat=True)
blog_years = sorted(set(blog_years), reverse=True)
It might not be what you exactly expects (it can return years without blog posts):
from datetime import date
from django.db.models import Min
def blog_years():
current_year = date.today().year
queryset = Entry.objects.annotate(Min('date')).order_by('date')
if queryset:
oldest_year = queryset[0].date.date().year
else:
oldest_year = current_year
return range(oldest_year, current_year + 1)
ModelName.objects.dates('column_name', 'year')

Using localtime in a where clause for GqlQuery

I'm trying to understand how I can use the local server time to quickly filter results on google appengine. It seems to me that there should be a simple way of doing this using DATETIME(time.localtime()).
For example (where 'timestamp' is of type db.DateTimeProperty)...
q = db.GqlQuery("SELECT * FROM LiveData WHERE timestamp > DATETIME(:1)", time.localtime())
Is there a GqlQuery and/or python construct that lets me do this with one method call? It seems as though I need to create strings for DATETIME() parameters.
You do not have to create strings when querying DateTimeProperty types. Try this:
import datetime
q = db.GqlQuery("SELECT * FROM LiveData WHERE timestamp > :1", datetime.datetime.now())

Categories

Resources