How to fix RuntimeWarning: DateTimeField Question.date_time received a naive datetime? - django

I want to delete 60 seconds old records but I am getting this error
RuntimeWarning: DateTimeField Question.date_time received a naive datetime (2022-08-27 16:09:30.659947) while time zone support is active.
def delete(self,request):
expiry_date_time = datetime.now() - timedelta(seconds=60)
print('Expiry time = ',expiry_date_time)
count = Question.objects.filter(date_time__gte = expiry_date_time).delete()
User.objects.all().update(total_question_added=0)
resp = {'resp' : 'All questions deleted.','Total question deleted':len(count)}
return Response(resp)

use timezone.now() [Django-doc] instead, this will add the timezone to the timestamp:
from django.http import JsonResponse
from django.utils.timezone import now
# …
def delete(self, request):
expiry_date_time = now() - timedelta(seconds=60)
count, __ = Question.objects.filter(date_time__gte=expiry_date_time).delete()
User.objects.update(total_question_added=0)
return JsonResponse(
{'resp': 'All questions deleted.', 'Total question deleted': count}
)

Related

How to remove an already selected option from options list to avoid double bookings

I've been scratching my head with this for 2 days hoping for a sudden brainwave and getting nowhere. I've completely drawn a blank with my logic and all attempts have resulted in me breaking my code. I'm trying to get it so that on a specific date, if a user has already selected a time slot with a selected barber, that that time slot will be removed from the list of time slots, so it cannot be selected again by another user.
From models.py
from django.db import models
import datetime
from django.core.validators import MinValueValidator
from django.contrib.auth.models import User
SERVICES = (
('Gents Cut', 'Gents Cut'),
('Kids Cut', 'Kids Cut'),
('Cut and Shave', 'Cut and Shave'),
('Shave Only', 'Shave Only'),
)
TIME_SLOTS = (
('9.00 - 10.00', '9.00 - 10.00'),
('10.00 - 11.00', '10.00 - 11.00'),
('11.00 - 12.00', '11.00 - 12.00'),
('12.00 - 13.00', '12.00 - 13.00'),
('13.00 - 14.00', '13.00 - 14.00'),
('14.00 - 15.00', '14.00 - 15.00'),
('15.00 - 16.00', '15.00 - 16.00'),
('16.00 - 17.00', '16.00 - 17.00'),
('17.00 - 18.00', '17.00 - 18.00'),
)
BARBER_NAME = (
('Nathan', 'Nathan'),
('Chris', 'Chris'),
('Ben', 'Ben'),
('Dan', 'Dan'),
)
class Booking(models.Model):
date = models.DateField(validators=[MinValueValidator(datetime.date.today)])
time = models.CharField(max_length=50, null=True, choices=TIME_SLOTS)
barber = models.CharField(max_length=50, null=True, choices=BARBER_NAME)
service = models.CharField(max_length=50, null=True, choices=SERVICES)
customer = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"{self.customer} has booked {self.service} on {self.date} at {self.time} with {self.barber}"
from views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views import generic, View
from django.contrib import messages
from django.http import HttpResponseRedirect
from .models import Booking
from .forms import BookingForm
#login_required()
def make_booking(request):
if request.method == "POST":
form = BookingForm(request.POST)
if form.is_valid():
booking_form = form.save(commit=False)
booking_form.customer = request.user
booking_form.save()
messages.success(request, ('Your booking is awaiting confirmation'))
return HttpResponseRedirect('/bookings')
else:
form = BookingForm()
return render(request, 'bookings.html', {'form': form})
from forms.py
from .models import Booking
import datetime
from django import forms
class DatePicker(forms.DateInput):
input_type = 'date'
class BookingForm(forms.ModelForm):
class Meta:
model = Booking
fields = ('date', 'time', 'barber', 'service',)
widgets = {
'date': DatePicker(),
}
One way or another you will need another view to accept the selected date and return the available time slots. If you were to do this via AJAX then your view might look something like this:
import json
from datetime import datetime
def get_time_slots(request):
# get the date in python format, sent via ajax request
date = datetime.strptime(request.GET.get('date'), '%Y-%m-%d')
# get all times from bookings on the provided date
booked_slots = Booking.objects.filter(date=date).values_list('time', flat=True)
available_slots = []
for slots in TIME_SLOTS:
if slots[0] not in booked_slots:
available_slots.append(slots)
times_as_json = json.dumps(available_slots)
return JsonResponse(times_as_json)
A better way, imo, would be to create new models for time slots, services, and barbers. Firstly, you are not hardcoding information and can dynamically change things in the DB. Secondly, you can generate a very slick query to get the available time slots for a day, barber, service, etc. You can also set general availability by linking certain barbers to certain time slots, depending on the hours they work.

Django context processor 'AnonymousUser' object is not iterable

I'm new to Django and have the below context processor which passes some data which is displayed in the header. everything works ok until the user logs out which should direct them back to the login screen however I get the below error.
here is the code
from . models import Job
from datetime import date
def add_variable_to_context(request):
today = date.today()
engineers_jobs = Job.objects.filter(date_due__lte = today).filter(assigned_to=request.user)
engineer_overdue = 0
for job in engineers_jobs:
engineer_overdue += 1
return {
'engineers_jobs': engineers_jobs,
'engineer_overdue':engineer_overdue,
}
I then tried the below
from . models import Job
from datetime import date
def add_variable_to_context(request):
if request.user.is_authenticated:
today = date.today()
engineers_jobs = Job.objects.filter(date_due__lte = today).filter(assigned_to=request.user)
engineer_overdue = 0
for job in engineers_jobs:
engineer_overdue += 1
return {
'engineers_jobs': engineers_jobs,
'engineer_overdue':engineer_overdue,
}
but that displayed the following error
can someone help me where I am going wrong?
Thanks
Context processors must return a dictionary.
When the user is not logged in you are currently returning None, you should return an empty dictionary instead
from . models import Job
from datetime import date
def add_variable_to_context(request):
if request.user.is_authenticated:
today = date.today()
engineers_jobs = Job.objects.filter(date_due__lte = today).filter(assigned_to=request.user)
engineer_overdue = 0
for job in engineers_jobs:
engineer_overdue += 1
return {
'engineers_jobs': engineers_jobs,
'engineer_overdue':engineer_overdue,
}
return {}

Django DateTimeField received a naive datetime while time zone support is active

I'm using Django 2.2
In my application, timezone support is enabled by USE_TZ=True in the settings file.
I have models with DateTime field created.
I need to filter data based on the date. The date can be provided by the user or else it will be default to now().
This is what I'm doing
from datetime import datetime, timedelta
from django.utils import timezone
class Generator:
def __init__(self, start_date=None, end_date=None):
if end_date:
self.end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
else:
self.end_date = timezone.now().date()
if start_date:
self.start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
else:
self.start_date = self.end_date - timedelta(days=7)
def get_query(self, d):
query = MyModel.objects.filter(
d__in=d,
created__gte=start_date,
created__lte=end_date
)
return query
But this is giving error
RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2020-02-28 00:00:00) while time zone support is active.
How can I get this issue solved?
When time zone support is enabled, the database layer expects to receive only aware datetimes from your code. This warning occurs when it receives a naive datetime. This indicates that you haven’t finished porting your code for time zone support. check documentation.
You need to change naive datetime to your project timezone datetime by using make_aware() function. For that you have to update your code like below.
from datetime import datetime, timedelta
from django.utils import timezone
class Generator:
def get_mytimezone_date(original_datetime):
new_datetime = datetime.strptime(original_datetime, '%Y-%m-%d')
tz = timezone.get_current_timezone()
timzone_datetime = timezone.make_aware(new_datetime, tz, True)
return timzone_datetime.date()
def __init__(self, start_date=None, end_date=None):
if end_date:
self.end_date = self.get_mytimezone_date(end_date)
else:
self.end_date = timezone.now().date()
if start_date:
self.start_date = self.get_mytimezone_date(start_date)
else:
self.start_date = self.end_date - timedelta(days=7)
def get_query(self, d):
query = MyModel.objects.filter(
d__in=d,
created__gte=start_date,
created__lte=end_date
)
return query
I hope this will help you :)
You can add the following code to ensure the start_date and end_date having timezone info.
E.g.
tz = timezone.get_current_timezone()
start_date = start_date.replace(tzinfo=tz)
end_date = end_date.replace(tzinfo=tz)
To not get a naive datetime, if myday is a string representing a date, convert it directly to a date this way:
from time import strptime
myday = date(*strptime(myday, "%Y-%m-%d")[:3])
This method avoids having to translate from naive to aware datetime.

Django: name 'request' is not defined when try to filter event that has been accepted by User

I am trying to filter an event that is only accepted by the current login-user, however the error "name 'request' is not defined" continues to pop-up. I have tried self.request user but it's still not working!
from datetime import datetime, timedelta
from calendar import HTMLCalendar
from cal.models import Event
from django.contrib.auth.models import User
class Calendar(HTMLCalendar):
def __init__(self, year=None, month=None):
self.year = year
self.month = month
super(Calendar, self).__init__()
# formats a day as a td
# filter events by day
def formatday(self, day, events):
events_per_day = events.filter(start_time__day=day, acceptor=self.request.user )
d = ''
for event in events_per_day:
# filter event that only accepted by user
if event.acceptor == User:
d += event.get_absolute_url()
if day != 0:
return f"<td><span class='date'>{day}</span><ul> {d} </ul></td>"
return '<td></td>'
# formats a week as a tr
def formatweek(self, theweek, events):
week = ''
for d, weekday in theweek:
week += self.formatday(d, events)
return f'<tr> {week} </tr>'
def formatmonth(self, withyear=True, ):
events = Event.objects.filter(start_time__year=self.year, start_time__month=self.month)
cal = f'<table border="0" cellpadding="0" cellspacing="0" class="calendar">\n'
cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n'
cal += f'{self.formatweekheader()}\n'
for week in self.monthdays2calendar(self.year, self.month):
cal += f'{self.formatweek(week, events)}\n'
return cal
I know its late reply but I face the similar prob recently. Here's my solution:
create a attribute name user or anything to store the id and get that from parameter.
def __init__(self, year=None, month=None, user=None):
self.year = year
self.month = month
self.user = user
super(Calendar, self).__init__()
like this pass the user when creating the object in views.py
user = self.request.user
cal = Calendar(d.year, d.month, user)
and then use as you like:
events_per_day = events.filter(start_time__day=day, acceptor=self.user )

django restful filtering by derived field

I was wondering if I can use a serializer to add two columns of a database, package it, and as a bonus FILTER by it.
models.py
class Snippet(models.Model):
time1= models.DateTimeField()
time2 = models.DateTimeField()
serializers.py
class SnippetSerializer(serializers.ModelSerializer):
sometime= UnixEpochDateField(source = 'time1') # special serializer that converts a datetime to epoch (below)
sometime2= UnixEpochDateField(source = 'time2') # special serializer that converts a datetime to epoch (below)
sometime_SUM = sometime + sometime2 # THIS DOES NOT WORK!
class Meta:
model = Snippet
fields = ('sometime_SUM')
class UnixEpochDateField(serializers.DateTimeField):
def to_native(self, value):
""" Return epoch time for a datetime object or ``None``"""
import time
try:
return calendar.timegm(value.utctimetuple())
except (AttributeError, TypeError):
return None
def from_native(self, value):
import datetime
try:
value = float(value)
except:
raise serializers.ValidationError("Not a number. Input: %s %s"%(type(value), value))
if value < 0:
raise serializers.ValidationError("Cannot be less than 0. Input: %s"%value)
return datetime.datetime.utcfromtimestamp(float(value))
views.py
class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
filter = ('sometime_SUM') # THIS DOES NOT WORK!
def get(self, request, format='json'):
snippets = Snippet.objects.all()
filter = SnippetFilter(request.GET, queryset = snippets) # THIS DOES NOT WORK!
serializer = SnippetSerializer(filter, many=True)
return Response(serializer.data)
I have highlighted the code that doesn't work that I naively thought would work.
The url command I want to use is /someurl/snippets/?sometime_SUM>4
EDIT:
Apparently, I can't filter by a serialize field. So let me modify my question to, can I filter by time1, except when I input the time from my website to the API, i am using EPOCH time, instead of the time1, DATETIME
Thanks #mariodev