Oscar Parra
Oscar Parra

Reputation: 185

ndb query error with datetime field - Google App Engine

I'm having a problem and I don't find any information about.

I define a field in my model like this.

class Dates(ndb.model):
    ...
    date = ndb.DateTimeProperty(required = True) # I want to store date and time
    ...

Later I try a query (now I want all the dates for a day, I don'tn mind the time):

kl = Dates.query(ndb.AND(Dates.date.year == year,
                         Dates.date.month == month,
                         Dates.date.day == day),
                 ancestor = customer.key).fetch(keys_only = True)
dates = ndb.get_multi(kl)

But I get this error log: AttributeError: 'DateTimeProperty' object has no attribute 'year'

I don't know why. I've tried Dates.date() == date, Dates.date == date (<-DateTime obj), ...

My DB is still empty but I suppose this doesn't mind because I'll never have dates for every possible days.

Anybody knows why? Should I go with GQL instead?

Upvotes: 11

Views: 7941

Answers (4)

user784435
user784435

Reputation:

I expanded @Guido van Rossum code snippet to include <> and timedelta for calculations, mostly for my own satisfaction

import datetime
from datetime import timedelta

from google.appengine.ext.ndb import *

class D(Model):
  d = DateProperty()

now = datetime.date.today()
date1 =  now-timedelta(+500)
date2 =  now-timedelta(+5)

d1 = D(d=now)
d2 = D(d=date1)
d3 = D(d=date2)

d1.put()
d2.put()
d3.put()

date2 =  now-timedelta(+50)

result1 = D.query(D.d == now).fetch(4)
result2 = D.query(D.d > date2).fetch(2)
result3 = D.query(D.d < date2).fetch(2)

result4 = D.query(D.d >= date2, D.d <= now).fetch(2)

print result1
print "+++++++"
print result2
print "+++++++"
print result3
print "+++++++"
print result4

Upvotes: 1

Guido van Rossum
Guido van Rossum

Reputation: 16890

Use a DateProperty. Then you can use a simple == query:

>>> import datetime
>>> from google.appengine.ext.ndb import *

>>> class D(Model):
...   d = DateProperty()
...

>>> d = D(d=datetime.date.today())

>>> d.put()
Key('D', 9)

>>> d
D(key=Key('D', 9), d=datetime.date(2013, 2, 20))

>>> D.query(D.d == datetime.date.today()).fetch()
[D(key=Key('D', 9), d=datetime.date(2013, 2, 20))]

Upvotes: 2

Dmytro Sadovnychyi
Dmytro Sadovnychyi

Reputation: 6201

You can use "range" queries for this. See example below.

import datetime
date = datetime.datetime.strptime('02/19/2013', '%m/%d/%Y')
kl = Dates.query(
    ndb.AND(Dates.date >= date),
            Dates.date < date + datetime.timedelta(days=1))

Will fetch all datetime's with 02/19/2013.

Upvotes: 17

Lipis
Lipis

Reputation: 21835

What you are trying to achieve is not really possible, because you can only query for the whole date and not for some parts of it.

In order to achieve what you are trying there I would suggest you to add few more properties to your model:

class Dates(ndb.model):
    ...
    date = ndb.DateTimeProperty(requiered=True)
    date_year = ndb.IntegerProperty()
    date_month = ndb.IntegerProperty()
    date_day = ndb.IntegerProperty()
    ...

You could update these values on every save or you could use Model Hooks to do it automagically and then your new query will become:

kl = Dates.query(ndb.AND(Dates.date_year == year,
                         Dates.date_month == month,
                         Dates.date_day == day),
                 ancestor=customer.key).fetch(keys_only=True)
dates = ndb.get_multi(kl)

Upvotes: 7

Related Questions