Я хотел бы отправить электронное письмо всем пользователям, которые не вошли в дневник сегодня. Я хотел бы дать им до 8 вечера по местному времени, чтобы войти в запись в журнале, и все получилось, но код неопрятен, и мне интересно, есть ли более эффективный способ достижения sh моей цели.
В настоящее время я сохраняю смещение часового пояса пользователя при регистрации.
<style>
#clientTimezone {
opacity: 0;
width: 0;
float: left;
}
</style>
....
<form class="signup form-default row" id="signup_form" method="post" action="{% url 'account_signup' %}">
{% csrf_token %}
<input type="text" name="client_timezone" id="clientTimezone" required />
....
<script>
$(document).ready(function(){
var d = new Date();
$('#clientTimezone').val(moment().format('ZZ'))
})
</script>
А затем код электронной почты находится в моей команде управления dailyreminder.py, которая срабатывает каждые 10 минут. Я хотел бы продолжить делать это без сельдерея, если это возможно.
import arrow
from datetime import datetime, timedelta
from django.utils import timezone
from django.core.management.base import BaseCommand, CommandError
from django.db.models import Q
from django.core.mail import send_mail, send_mass_mail, EmailMultiAlternatives
from django.conf import settings
from dashboard.models import Entry
from dashboard.emails import email_daily_reminder
from redwoodlabs.models import UserProfile
from identity.strings import GLOBAL_STRINGS
LOCAL_TIME_TO_EMAIL = 20 # 8:00 PM
MAX_LOCAL_TIME_TO_EMAIL = 24 # 12:00 AM
USER_BATCH_SIZE = 10
class Command(BaseCommand):
help = 'Email users daily reminder to reflect'
def handle(self, *args, **options):
# UserProfile model has last_notified (datetimefield) and timezone (char field)
# get current time in utc
time_now = arrow.utcnow()
# Get timezone where it's 8PM
start_tz = LOCAL_TIME_TO_EMAIL - time_now.hour
end_tz = MAX_LOCAL_TIME_TO_EMAIL - time_now.hour
# Get a list of timezones where it is between 8pm to 12am
timezones = list()
for tz in range(start_tz, end_tz):
if tz > 14:
tz = 24 - tz
timezones.append('-' + str(tz).zfill(2) + '00')
else:
timezones.append('+' + str(tz).zfill(2) + '00')
time_now_local = time_now.replace(minute=0, second=0)
time_yesterday = time_now.shift(days=-1)
# Get all users with the ff cases:
# - who have not been notified today
# - who have not been notified at all
# - who have not been notified in the last 24hrs
users_to_email = UserProfile.objects.filter(Q(last_notified__isnull=True) |
(Q(timezone__in=timezones) & Q(last_notified__lt=time_now_local.datetime)) |
Q(last_notified__lt=time_yesterday.datetime)
).exclude(timezone__isnull=True)[:USER_BATCH_SIZE]
for profile in users_to_email:
user_time_now = time_now.to(profile.timezone)
user_today = user_time_now.floor('day')
last_notified_day = arrow.get(profile.last_notified).to(profile.timezone)
# Send email if last_notified was before today
if not profile.last_notified or last_notified_day.datetime < user_today.datetime:
self.stdout.write('Notifying %s' % profile)
email_sent = email_daily_reminder(profile.user, user_time_now.date())
# save somewhere they've been notified today?
self.stdout.write(self.style.SUCCESS('Notified %s' % profile.user.email))
profile.last_notified = user_time_now
profile.save()
Это работает (или, по крайней мере, пока), но я хотел спросить, есть ли лучший способ сделать это (особенно logi c вокруг часовых поясов), потому что я, скорее всего, снова буду использовать этот код в другом проекте и хотел бы изучить лучшие практики для него. Это кажется как у Django есть лучший способ сделать это.