Determine if an entity is created 'today' - python

I am creating an app which, on any given day, only one entity can be created per day. Here is the model:
class MyModel(ndb.Model):
created = ndb.DateTimeProperty(auto_now_add=True)
Since only one entity is allowed to be created per day, we will need to compare the MyModel.created property to today's date:
import datetime
class CreateEntity(webapp2.RequestHandler):
def get(self):
today = datetime.datetime.today()
my_model = MyModel.query(MyModel.created == today).get()
if my_model:
# print("Today's entity already exists")
else:
# create today's new entity
The problem is that I cannot compare the two dates like this. How can I check if an entity was already created 'today'?

I ended up changing the property from DateTimeProperty to DateProperty. Now I am able to do this:
today_date = datetime.datetime.today().date()
today_entity = MyModel.query(MyModel.created == today_date).get()

You are comparing a DateTime object with a Date object.
Instead of
my_model = MyModel.query(MyModel.created == today).get()
use
my_model = MyModel.query(MyModel.created.date() == today).get()

Seems like the only one solution is to use a "range" query, here's a relevant answer https://stackoverflow.com/a/14963648/762270

You can't query by created property using == since you don't actually know the exact creation datetime (which is what you'll find in created due to the auto_now_add=True option)
But you could query for the most recently created entity and check if its creation datetime is today. Something along these lines:
class CreateEntity(webapp2.RequestHandler):
def get(self):
now = datetime.datetime.utcnow()
# get most recently created one:
entity_list = MyModel.query().order(-MyModel.created).fetch(limit=1)
entity = entity_list[0] if entity_list else None
if entity and entity.created.year == now.year and \
entity.created.month == now.month and \
entity.created.day == now.day:
# print("Today's entity already exists")
else:
# create today's new entity
Or you could compute a datetime for today's 0:00:00 am and query for created bigger than that.
Or you could drop the auto_now_add=True option and explicitly set created to a specific time of the day (say midnight exactly) and then you can query for the datetime matching that time of day today.

Using a range query for a single specific known value you want to lookup is overkill and expensive, I would use one of these 2 solutions:
1 - Extra Property
Sacrifice a little space with an extra property, though since it's one per day, it shouldn't be a big deal.
from datetime import datetime
class MyModel(ndb.Model):
def _pre_put_hook(self):
self.date = datetime.today().strftime("%Y%m%d")
created = ndb.DateTimeProperty(auto_now_add=True)
date = ndb.StringProperty()
class CreateEntity(webapp2.RequestHandler):
def get(self):
today = datetime.today().strftime("%Y%m%d")
my_model = MyModel.query(MyModel.date == today).get()
if my_model:
logging.info("Today's entity already exists")
else:
# MyModel.date gets set automaticaly by _pre_put_hook
my_model = MyModel()
my_model.put()
logging.info("create today's new entity")
2 - Use [today] as Entity ID (preferred)
I would rather use today as the ID for my Entity, that's the fastest/cheaper/optimal way to retrieve your entity later. It could also be a combination with something else, i.e. ID=<userid+today>, in case that entity is per user, or maybe just add userid as a parent (ancestor). So it would be something like this:
from datetime import datetime
class MyModel(ndb.Model):
created = ndb.DateTimeProperty(auto_now_add=True)
class CreateEntity(webapp2.RequestHandler):
def get(self):
today = datetime.today().strftime("%Y%m%d")
my_model = MyModel.get_by_id(today)
if my_model:
logging.info("Today's entity already exists")
else:
my_model = MyModel(id=today)
my_model.put()
logging.info("create today's new entity")

Related

How can I filter a datetime with a date in Tortoise-ORM?

I am creating an application in fastapi and I am using Tortoise-ORM as orm. I have the following model:
from tortoise import fields
from app.models.base_class import Base
class Announcement(Base):
name = fields.CharField(max_length=64, null=False)
description = fields.TextField()
date = fields.DatetimeField(auto_now=True)
# ORM relationship between Announcement and User entity
user = fields.ForeignKeyField(
"models.User",
related_name="announcements",
on_delete=fields.CASCADE
)
And I need to get all the "announcements" of the current day, the problem is that my date field is of type datetime and I want to filter by day (without considering the time). How can I do this with tortoise-orm? something like this:
async def get_today_announcement(self):
today = datetime.datetime.now().date()
return await self.model.filter(date=today).all()
(The above does not work since it returns an empty list when the hours do not match).
This is what worked for me:
async def get_today_announcement(self):
today = datetime.datetime.now()
return await self.model.filter(
date__year=today.year,
date__month=today.month,
date__day=today.day
).all()

Python/Django date query: Unsupported lookup 'date' for DateField or join on the field not permitted

I have a simple method. Entries are entries in a time sheet application where employees enter their hours.
class Entry(m.Model):
""" Represents an entry in a time_sheet. An entry is either for work, sick leave or holiday. """
# type choices
WORK = 'w'
SICK = 's'
VACATION = 'v'
type_choices = (
(WORK, 'work'),
(SICK, 'sick leave'),
(VACATION, 'vacation'),
)
# meta
cr_date = m.DateTimeField(auto_now_add=True, editable=False, verbose_name='Date of Creation') # date of creation
owner = m.ForeignKey(User, editable=False, on_delete=m.PROTECT)
# content
type = m.CharField(max_length=1, choices=type_choices, default='w')
day = m.DateField(default=now)
start = m.TimeField(blank=True) # starting time
end = m.TimeField(blank=True) # ending time
recess = m.IntegerField() # recess time in minutes
project = m.ForeignKey(Project, on_delete=m.PROTECT)
#classmethod
def get_entries_for_day(cls, user, day):
""" Retrieves any entries for the supplied day. """
return Entry.objects.filter(day__date=day, owner=user).order_by('start')
However, when I try to run my project like this, it terminates with the following error code:
"Unsupported lookup 'date' for DateField or join on the field not
permitted."
I don't quite understand the message. The specified field is a date field which has no further restrictions. Any hints would be appreciated.
There's no such thing as a __date lookup on a DateField; the field is already a date.
It's not clear what you are trying to compare this field with. Is the day you are passing into that method an integer, or a date? If it's also a date then you should just compare them directly.
I'm facing an issue with Django-filters, The filter was not taking the same date range while I was using it. so I added date__lte/gte in lookup_expr.something like this.
from_date = django_filters.DateFilter(field_name="created_at", lookup_expr='date__gte')
to_date = django_filters.DateFilter(field_name="created_at", lookup_expr='date__lte')

Set value for Django DurationField type in query

I want to pass value to DurationField of Django and store it into database.
After check the documentation, I thought we should use timedelta datatype to set Duratioin Field value. Like following code
record = Record(ID = 1,Duration = DurationField(timedelta(minutes=20)))
I also tried to using string type and integer type to set Duration's value, but they can't work. So I wander how should we set the value for DurationField type? I'm using the SQLite database.
My model:
TimeRecord(models.Model):
duration = models.DurationField()
Instantiate:
record = TimeRecord(duration = timedelta(hours=5))
record.save()
Here is an example:
from datetime import timedelta
from django.db import models
class TimeRecord(models.Model):
duration = models.DurationField(default=timedelta(minutes=40))
And you can create a record like this :
from datetime import timedelta
# create a new record
record1 = TimeRecord.objects.create()
record1.duration
# output : datetime.timedelta(0, 2400)
# you can create an another
record2 = TimeRecord.objects.create(duration=timedelta(minutes=20))
record2.duration
# output : datetime.timedelta(0, 1200)

how to remove if end date is expired in python google app engine

My gql model is
start_date = db.DateTimeProperty()
end_date = db.DateTimeProperty()
my class is
class GetHandler(BaseHandler):
def get(self):
promos = Promotion.all()
self.render_response("/admin/promotion/index.html", promos=promos)
if end_date is expired [end_date<datetime.now] it should remove from my admin panel.
Based on Tim 's answer:
now = datetime.now() # get current datetime
q = db.Query(Promotion)
q = q.filter('end_date <', now)
for promo in q.run(): # loop over filtered promos
promo.delete() # delete instance from datastore
The documentation discourages the use of fetch instead of run. And it's probably a bad idea to fetch all the promos.
Compare the dates and act accordingly
promos = Promotion.all().fetch() # fetch all promos
now = datetime.now() # get current datetime
for promo in promos: # loop over all promos
if promo.end_date > now: # compare promo date to 'now'
promo.delete() # delete instance from datastore
comparing date(time)s is as simple as using > or <

Django/Python: How to group queryset results by date?

I have a model for image uploads, that looks something like this:
from django.db import models
from django.contrib.auth.models import User
import datetime
class ImageItem(models.Model):
user = models.ForeignKey(User)
upload_date = models.DateTimeField(auto_now_add = True)
last_modified = models.DateTimeField(auto_now = True)
original_img = models.ImageField(upload_to = img_get_file_path)
I want to query all instances of ImageItem that belong to a particular user, and group them according to date uploaded. For example, for some user, I want a group for April 9 2013, another for April 12 2013, etc. (assuming that they uploaded one or more images on those dates).
I'm thinking I run a simple query, like,
joes_images = ImageItem.objects.filter(user__username='joe')
But then how could I group them by day published? (assuming he did not publish every day, only on some days)
The function would have to return all the groups of images.
why don't you do as following?
joes_images = ImageItem.objects.filter(user__username='joe') # your code
upload_dates = set([(i.year, i.month, i.day) for i in joes_images]) # set of upload_date
joes_images_separated = dict([(d, []) for d in upload_dates])
for d in upload_dates:
for i in joes_images:
if (i.year, i.month, i.day) == d:
joes_images_separated[d].append(i)
Here, upload_dates is a set of dates in joes_images and you get joes_images_separated as a dict (keys are dates, values are lists of joes_images for each date).
I'm sorry for a little dirty code. I think this works. for your information.

Categories