I've defined a model as follows (Shortened it for the question)
from datetime import datetime, date, timedelta
class Case(models.Model):
received_email_sent = models.DateTimeField(null=True, blank=True, default=None)
def send_received_email(self):
message = settings.EMAIL_HEADER + self.case_received_email() + settings.EMAIL_FOOTER
send_mail('Subject here', message, settings.EMAIL_HOST_USER, ['xxx#xxx.com'], fail_silently=False)
self.received_email_sent = datetime.now()
and in the view I call send_received_email on an existing object. I know that the send_received_email block is being entered because I'm receiving the emails every time I test this out, but the self.received_email_sent = datetime.now() part is leaving that field as its default value (None) every time. Here's the relevant part of the view:
from logbook.models import Case
def job_email(request, case_id):
case = get_object_or_404(Case,pk=case_id)
case.send_received_email()
return HttpResponseRedirect('/jobs/'+str(case.case_id))
I have also tried an alternative method, where saving the field is done in the view instead of the model, like so:
models:
class Case(models.Model):
received_email_sent = models.DateTimeField(null=True, blank=True, default=None)
def send_received_email(self):
message = settings.EMAIL_HEADER + self.case_received_email() + settings.EMAIL_FOOTER
send_mail('Subject here', message, settings.EMAIL_HOST_USER, ['xxx#xxx.com'], fail_silently=False)
#self.received_email_sent = datetime.now()
views:
from datetime import datetime
from logbook.models import Case
def job_email(request, case_id):
case = get_object_or_404(Case,pk=case_id)
case.send_received_email()
case.received_email_sent = datetime.now()
return HttpResponseRedirect('/jobs/'+str(case.case_id))
I have also tried both of the above routes with various tweaks like removing the brackets on now() and changing from datetime import datetime to just import datetime. No joy. Thanks for having a look at this.
You need to call self.save() at the end of send_received_email().
Related
I have to write a serializer that returns datetime in the following formats:
2012-01-01T13:00:00+00:00 (utc_with_timezone) 2020-01-01T09:00:00 (must be in localtime without timezone info)
class SomeResponse(serializers.Serializer):
modified = serializers.DateTimeField() # AutoLastModifiedField(_('modified'))
local_time = serializers.DateTimeField()
but the response for modified field contains miliseconds: 2022-01-01T18:14:05.378897+05:00the response for local_time field contains timezone info and I have to convert it to local time
How can I manipulate the output format without changing the settings for the whole project?
I solved the problem by overriding to_representation of serializers.DateTimeField:
class SomeResponse(serializers.Serializer):
modified = TimeZoneWithUTCField()
local_time = TimeZoneWithUTCField()
class TimeZoneWithUTCField(serializers.DateTimeField):
def to_representation(self, value):
if not value:
return None
value = value.strftime("%Y-%m-%dT%H:%M:%S%z")
if value.endswith('+0000'):
value = value[:-5] + '+00:00'
return value
I want to save a string as time format to store it in the database for a django project,
Here's my utils.py file:
import datetime
import re
import math
from django.utils.html import strip_tags
def count_words(text_string):
word_string = strip_tags(text_string)
matching_words = re.findall(r'\w+', word_string)
count = len(matching_words)
return count
def get_read_time(text_string):
count = count_words(text_string)
read_time_min = math.ceil(count/200.0) #Assuming 200 words per min Reading
read_time = str(datetime.timedelta(minutes=read_time_min))
return read_time
Here's the required portion of the models.py file:
class Post(models.Model):
read_time = models.TimeField(null=True, blank=True)
Here's the required portion of the views.py file:
class PostDetailView(DetailView):
model = Post
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
texts = self.object.content
# print(texts)
read_time=get_read_time(texts)
# print(read_time)
Post.objects.create(read_time=datetime.strptime(read_time, "%H:%M:%S"))
return context
The Output format of the string is 0:02:00 this I want to save it in the database as datetime field.
But I am encountering this error:-
Exception Type: ValueError at /post/this-blog-contains-an-image-with-it/
Exception Value: 's' is a bad directive in format '%H:%MM:%ss'
A TimeField [Django-doc] expects a time object, not a datetime object. You can make use of the .time() method [Django-doc] to retrieve the time part:
class PostDetailView(DetailView):
model = Post
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
texts = self.object.content
read_time=get_read_time(texts)
Post.objects.create(read_time=datetime.strptime(read_time, '%H:%M:%S').time())
return context
It is however rather odd to construct a string instead of returning the timedelta part itself:
def get_read_time(text_string):
count = count_words(text_string)
read_time_min = math.ceil(count/200.0) #Assuming 200 words per min Reading
return datetime.timedelta(minutes=read_time_min)
Then you can use this timedelta to obtain the time:
class PostDetailView(DetailView):
model = Post
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
texts = self.object.content
read_time=get_read_time(texts)
Post.objects.create(read_time=(datetime.datetime.min + read_time).time())
return context
It furthermore does not make sense to construct objects in the get_context_data. A GET request is supposed to have no side-effects, so you should only make database changes for POST, PUT, PATCH, DELETE, etc. requests. Not in the get_context_data.
I have a dateTime field in a model. The dateTime field named breakfast_start_time takes an input.
I have to save another variable or timefield(whichever is better) named breakfast_attendence_start_time whose value should be automatically saved 15 minutes less than the breakfast_start_time.
For this we use
def save(self, *args, **kwargs):
#do something
super().save(*args, *kwargs)
I am trying to do
breakfast_attendence_start_time = breakfast_start_time - time(15,0)
but it is giving error that
class TimeField does not define '_sub_', so the '-' operator cannot be used on its instances
Edited:
Here is the full code
class Hostel(models.Model):
name = models.CharField(max_length=15)
breakfast_start_time = models.TimeField()
lunch_start_time = models.TimeField()
snacks_start_time = models.TimeField()
dinner_start_time = models.TimeField()
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
I am taking start time from admin panel and I want to add 4 more variable/field like breakfast_attendence_start_time whose value should be saved automatically 15 minutes earlier than breakfast_start_time how can I achive that.
You should use timedelta to sub specific time with DateTime field. Such as
import datetime
time_before_15_minute = datetime.datetime.now() - datetime.timedelta(minutes=15)
Use DateTimeField instead of TimeField and use timedelta to make substractions
from datetime import datetime, timedelta
n = datetime(2019, 10, 4, 12, 30)
m = n - timedelta(minutes = 15) # m is now datetime(2019, 10, 4, 12, 15)
You can play with the DateTimeField but this will return time of when this function was called or used. Hope it helps
from django.utils import timezone
class AKA(models.Model):
create_time = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.create_time
Take the example model as follows:
import datetime
class Calendar(models.Model)
def now():
return datetime.date.today()
def 24hrslater():
return datetime.date.today() + datetime.timedelta(days=1)
now = models.DateTimeField(default=now)
24hrslater = models.DateTimeField(default=24hrslater)
Is there a way to extract just the date from these date time fields? I have tried the following (as suggested on another thread):
todaysdate = now.date()
But had no success with it. The error that comes up on the command line when running "python manage.py check" is:
AttributeError: 'DateTimeField' object has no attribute 'date'
Is there a way to do this?
def now():
return datetime.today().date()
this will return the current date
Calendar.objects.filter(datetimefield__date='your_date')
I'm not sure that I understand your question correctly, but you can get the date from DateTimeFields like this.
from django.db import models
from django.utils import timezone
class Calendar(models.Model):
now = models.DateTimeField(default=timezone.now)
twenty_four_hours_later = models.DateTimeField(
default=lambda: timezone.now() + timezone.timedelta(hours=24))
c = Calendar()
print(c.now.date())
print(c.twenty_four_hours_later.date())
I'm making a website using django.
class Member(models.Model):
...
end_date = models.DateField(blank=True, default=(datetime.now() + timedelta(days=30)))
Membership_status = models.IntegerField(blank=True, null=True, default=1) # 1 = active, 0=deactivate, 2=refund
What I want to do is comparing the end_date field to today.date every 1.a.m. and if today's day < end_date, Membership_status field is changed to 0 automatically.
I heard I should use django-kronos(https://github.com/jgorset/django-kronos).
But I can't understand the using method.
Is there anyone can tell me details how I implement what I want?
Any help will be very helpful to me, thanks!
First of all, this is not an answer to your original query, but merely a suggestion for your future,
Never pass a function call into your field defaults. If you did, the function would be evaluated at the time of your migrations. If you look into the migration files you can see for sure. Instead wrap it in a function and pass that as a callable.
Eg:
from django.utils import timezone
def TODAY():
return timezone.now().date()
def NEXT_MONTH_DAY():
return TODAY() + timedelta(days=30)
Now, in your models,
class Member(models.Model):
...
end_date = models.DateField(blank=True, default=NEXT_MONTH_DAY)
This way the function NEXT_MONTH_DAY is called whenever an instance of Member is created.
EDIT:
For your original query, I haven't tested the code, but I suppose you are looking for maybe something like this,
import kronos
#kronos.register('0 1 * * *')
def the_task():
for member in Member.objects.all():
if TODAY() == member.end_date:
member.Membership_status = 0
member.save()