I am attempting to retrieve all objects with a time-to-live of less than 5 seconds using Django's ORM in Python. However, my current approach is not producing the expected results. Can you help me understand what I am doing wrong and how I can correctly retrieve these objects?
queryset.py
def ttl_expire_list(self):
query = self.filter(is_remove=False,ttl__range=[timezone.now() + timedelta(seconds=5), timezone.now()]).order_by("-ttl")
# query = self.filter(is_remove=False).order_by("-ttl")
return query'
models.py
class Notification(models.Model):
sender = models.CharField(_("Sender"), max_length=100,null=True,blank=True)
receiver = models.CharField(_("Receiver"), max_length=100,null=True,blank=True)
message = models.TextField(_("Message"),null=True,blank=True)
is_read = models.BooleanField(_("Read") ,default=False,null=True,blank=True)
ttl = models.DateTimeField(_("Time to live"),null=True,blank=True)
create_time = models.DateTimeField(_("Created Time"), default = timezone.now)
Solution
def ttl_expire_list(self):
print("curen",timezone.now())
print("imte :",timezone.now() + timedelta(seconds=5))
query = self.filter(is_remove=False,ttl__range=(timezone.now() , timezone.now()+timedelta(seconds=50))).order_by("-ttl")
return query
First argument of range should be start date and then end date just swap the arguments:
ttl__range=[timezone.now(), timezone.now() + timedelta(seconds=5)]
Related
I've two tables in two database, say Policy in DB_A and Quote in DB_B.
Policy has a field result_reference which is the id of Quote table in DB_B
policy in DB_A
class Policy(models.Model):
result_reference = models.IntegerField()
policy_date = models.DateTimeField()
Quote in DB_B
class Quote(models.Model):
quote_type = models.IntegerField()
policy_type = models.CharField(max_length = 100)
policy_premium = models.IntegerField()
The policy type can be S for Single and M for Multiple
I want to get the policies with policy date after 30 days along with policy_type=M
What I've tried
import datetime
start_date = datetime.datetime.now() + datetime.timedelta(30)
p = Policy.objects.using(default_database).filter(policy_date__gte=start_date)
But this returns policies that have policy_type S and M. How can I filter it for policy type M?
If i understand you well, you can try:
take a list of the quotes with type M and filter the Policy by this list using in, and of cause you should apply valid using for each query.
m_quotes = Quote.objects.filter(policy_type='M').values_list('pk', flat=True)
m_quotes = list(m_quotes)
p = Policy.objects.using(default_database).filter(result_reference__in=m_quotes)
Hi i have some Django 11 project, my model look like
class Event(models.Model):
name = models.CharField(max_length=100, unique=True)
title = models.CharField(max_length=100)
info = models.CharField(max_length=100)
image = models.ImageField(upload_to='events/%Y/%m/%d')
start_date = models.DateField(default=timezone.now)
start_time = models.TimeField(default=timezone.now)
stop_date = models.DateField(default=timezone.now)
stop_time = models.TimeField(default=timezone.now)
place = models.ForeignKey('places.Place', on_delete=models.CASCADE)
company = models.ForeignKey('companies.Company', on_delete=models.CASCADE)
and my view look like
def place_website(request, place_id):
place_template = get_template('room.html')
place_obj = Place.objects.filter(id=place_id)
# filter for event obejts only for requested place, filtered for now and next events
place_event_now = Event.objects.filter(place=place_id, start_date=timezone.now().date, stop_date__gte=timezone.now().date)
place_events_next = Event.objects.filter(place=place_id, start_date=timezone.now(), stop_date__gte=timezone.now()).order_by('start_time')
place_context = {
'place_obj': place_obj,
'place_event_now': place_event_now,
'place_events_next': place_events_next,
}
return HttpResponse(place_template.render(place_context))
the thing i want to manage is to pass to template the list of filtered Event objects based on time.
Lets pick this line
place_event_now = Event.objects.filter(place=place_id, start_date=timezone.now().date, stop_date__gte=timezone.now().date)
it couse error "expected string or bytes-like object" but when i remove ".date" from "timezone.now()" error disappear (then filter do nothing) but i want to compare date to date and time to time.
How to do this properly ?
This approach to filter objects in view rather than in template is proper?
###### UPDATE ########
Its werid because after correction now i have no error but queryset is not filtered properly, look like only two first parameter is filtering ok and the another two is causing empty queryset.
place_event_now = Event.objects.filter(place=place_id, start_date=timezone.now().strftime('%Y-%m-%d'), start_time__lte=timezone.now().strftime('%H:%M:%S'), stop_time__gte=timezone.now().strftime('%H:%M:%S'))
I my database time is saved in format H:M:S and timezone.now().time() has different format so i modified filter with .strftime this didnt help, what i wont is to limit "place_event_now" queryset to particular object/objects that come true with condition start_time < currenttime < stop_time.
Another case is with place_event_next
place_events_next = Event.objects.filter(place=place_id, start_date=timezone.now().strftime('%Y-%m-%d'), stop_date__gte=timezone.now().strftime('%Y-%m-%d'), start_time__gt=timezone.now().strftime('%H:%M:%S')).order_by('start_time')
Event when i filter objects that start_time is greater than timezone.now() they still are in queryset.
Am I doing something wrong ?
I figured it out that timezone.now() return time not in my current timezone, i change it to timezone.localtime() and everything working perfect !!!
May be you need call date to date()
replace
filter(place=place_id, start_date=timezone.now().date, stop_date__gte=timezone.now().date)
# ^^^ ^^^
to
filter(place=place_id, start_date=timezone.now().date(), stop_date__gte=timezone.now().date())
# ^^^ ^^^
I have a model and I want to know if it is possible to set a condition that triggers a change in the model field. For example, I have a model
class BillboardTracker(models.Model):
client_name = models.CharField(max_length=400)
entry_date = models.DateTimeField(default=datetime.now)
duration = models.PositiveIntegerField()
expiry_date = models.DateField()
is_expired = models.BooleanField(default=False)
I want to know if it is possible to have a function in the model that makes is_expired equals to True when the expiry date is up. I tried this
def expire(self):
if datetime.now == self.expiry_date:
self.is_expired = True
but it's not working. Is it possible to implement this?
Use a #property
The simplest thing here is not to have an is expired field at all! It's not needed. What you need is a property.
class BillboardTracker(models.Model):
client_name = models.CharField(max_length=400)
entry_date = models.DateTimeField(default=datetime.now)
duration = models.PositiveIntegerField()
expiry_date = models.DateField()
#property
def is_expired(self):
if datetime.now > self.expiry_date:
return True
return False
Remember, you don't have a field in a database, if that field is the same as another field with a simple calculation. This automatically eliminates your head ache of having to flag items as expired.
If you want to find out if an object has expired.
if instance.is_expired == True:
print 'yes, that ones gone'
Filtering
If you wanted to retrieve a whole set of objects that have expired
BillboardTracker.objects.filter(expiry_date__le=datetime.now())
This is why I mentioned that you don't need to store a field that can be easily calculated.
Index advantage
In most RDBMS a boolean field (such as your is_expired column) cannot be indexed effectively. So that actually means the above query will be faster than a query on that boolean field provided you create an index on the expiry_date field.
You need to make two changes in this function,
Firstly use datetime.now() and secondly,
You might want to update your logic like this :
def expire(self):
if datetime.now() >= self.expiry_date:
self.is_expired = True
return True
else:
return False
Because sometimes both the values might not be exactly same but still BillboardTracker need is_expired = True for all previous dates.
And in your views :
def your_view(request):
instance = BillboardTracker.objects.get(id=some_id)
if instance.is_expired() == True:
print 'expired'
else:
print 'fresh'
Since I could not find the exact answer for me, I decided to ask.
I have the following two models:
class Schedule(models.Model):
transport = models.ForeignKey(Transport)
stop = models.ForeignKey(Stop)
from_to_stop = models.ForeignKey(Direction)
time = models.ManyToManyField(TimeTable)
type_day = models.ForeignKey(TypeDay)
created = models.DateTimeField(_('Created at'), auto_now_add = True)
updated = models.DateTimeField(_('Modified at'), auto_now = True)
class TimeTable(models.Model):
time_arrival = models.TimeField()
created = models.DateTimeField(_('Created at'), auto_now_add = True)
updated = models.DateTimeField(_('Modified at'), auto_now = True)
A script that must be dynamically added things in 'time' field on the 'Schedule'. Here's what I do:
time = self.get_or_create_time(time)
count = Schedule.objects.filter(time__in = [time]).count()
if not count:
schedule.time.add(time)
def get_or_create_time(self, time):
obj, created = TimeTable.objects.get_or_create(time_arrival=time)
return obj
Here I'm not getting the required result for me, because it searches the entire table if there is such a connection somewhere. I want to see if there is such a link only for the current object ' schedule ' is the current object. All I want is for him to see whether there is a connection with the ' TimeTable '. How to do this in Django?
For a start, there is no point in using __in with a single element which you then wrap in a list. The fact that you had to do that should have given you a hint that you are using the wrong predicate: just use the default (which is __eq, but since it's the default you can leave it out altogether).
Also, if you only want to know if an object exists, use .exists() rather than .count(), as the latter is a more expensive query if there can be multiple objects.
But basically your problem is simple. You want to filter the times belonging to a schedule: so, start with that schedule, not the whole Schedule model.
exists = self.times.filter(time_arrival=time.time_arrival).exists()
I have a Task model where every task has deadline.
class Tasks(models.Model):
assigned_to = models.ForeignKey('Users', related_name='user_assigned_to')
deadline = models.DateTimeField()
status = models.CharField(max_length=20,null=True)
I need to filter out task that has deadline date earlier than today's date with other filters.So I used this query:
all_task = Tasks.objects.filter(Q(assigned_to = i),Q(deadline<datetime.datetime.today()),~Q(status="Done"))
But this give me error:
NameError: name 'deadline' is not defined
If i changed the query to(just changing < sign to = ) :
all_task = Tasks.objects.filter(Q(assigned_to = i),Q(deadline=datetime.datetime.today()),~Q(status="Done"))
The above query returns me objects , but why it is not returning objects in case I use < or > with datetime?
Because using < is trying to use it as a name instead of a keyword argument.
..., Q(deadline__lt=datetime.datetime.today()), ....
"Field lookups"
have u try this one ??
all_task = Tasks.objects.filter(Q(assigned_to = i),Q(deadline__lt = datetime.datetime.today()),~Q(status="Done"))
I hope it will work.