I have an Event model, and each event will have different shows.
class Event(models.Model):
title = models.CharField(max_length=200)
class Show(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE)
date_time = models.DateTimeField(unique=True)
I have another Ticket model. Each ticket should be unique. Meaning each ticket will be unique and relate to a Show and a Seat.
class Ticket(models.Model):
show = models.ForeignKey(Show)
seat = models.ForeignKey(Seat)
class Meta:
unique_together = ('show', 'seat')
I need to create shows based on the start date and end date provide by the user. Suppose this is a JSON post:
{
"event_id": 1,
"start_date": "2018-02-16",
"end_date": "2018-02-20",
"time_list": ["11:00 AM", "8:00 PM"]
}
From the above JSON example, I need to create Show starting like this:
# Start with the start_date as the date, and for each time from the time_list
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-16 11:00 AM', "%Y-%m-%d %I:%M %p")
)
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-16 8:00 PM', "%Y-%m-%d %I:%M %p")
)
# Next date after the start_date, i.e., 16+1 = 17
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-17 8:00 PM', "%Y-%m-%d %I:%M %p")
)
.
.
.
# Create Show objects till the end_date and for each time from the time_list
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-20 8:00 PM', "%Y-%m-%d %I:%M %p")
)
Right now this is how I am creating Show objects:
def create_show_by_datetime(self, request):
event_id = request.data['event_id']
try:
event = Event.objects.get(id=event_id)
except Event.DoesNotExist:
return Response(
{'error': 'event with id: %s does not exist.' % event_id},
status=status.HTTP_400_BAD_REQUEST
)
start_date = request.data['start_date']
end_date = request.data['end_date']
time_list = request.data['time_list']
date_format = '%Y-%m-%d'
time_format = "%I:%M %p"
try:
datetime.strptime(start_date, date_format)
datetime.strptime(end_date, date_format)
for i in range(len(time_list)):
time = datetime.strptime(time_list[i], time_format)
except ValueError as e:
return Response(
{'error': 'Time was not in a supported format. %s' % e},
status=status.HTTP_400_BAD_REQUEST
)
delta_days = datetime.strptime(end_date, date_format).date() - datetime.strptime(start_date, date_format).date()
delta_days = delta_days.days + 1
dt = None
try:
with transaction.atomic():
for i in range(delta_days):
day = datetime.strptime(start_date, date_format) + timedelta(days=i)
for i in range(len(time_list)):
hrs = datetime.strptime(time_list[i], time_format).hour
mins = datetime.strptime(time_list[i], time_format).minute
dt = day + timedelta(hours=hrs, minutes=mins)
show = Show.objects.create(
event=event,
date_time=dt
)
return Response({"data": 'Post succesfull'}, status=status.HTTP_201_CREATED)
except IntegrityError as e:
return Response(
{
'error': "event with date and time already exsits. %s-%s-%s at %s:%s" % (
dt.day, dt.month, dt.year, dt.hour, dt.minute),
'detail': str(e)
}, status=status.HTTP_400_BAD_REQUEST
But I am hoping there's much more elegant way than how I am doing. I am using python 3, django 2 and django rest frameowork. How can I create Shows with the event, and date_time based on the event_id
, start_date
, end_date
and the time_list
?
You can create a Date object using the Date() constructor of java. util. Date constructor as shown in the following example. The object created using this constructor represents the current time.
To create a date, we can use the datetime() class (constructor) of the datetime module. The datetime() class requires three parameters to create a date: year, month, day.
Python Datetime module supplies classes to work with date and time. These classes provide a number of functions to deal with dates, times and time intervals. Date and datetime are an object in Python, so when you manipulate them, you are actually manipulating objects and not string or timestamps.
The Date object is a built-in object in JavaScript that stores the date and time. It provides a number of built-in methods for formatting and managing that data. By default, a new Date instance without arguments provided creates an object corresponding to the current date and time.
My approach is a little bit different. You said in the question tag that you are using django-rest-framework
.. So where are the serializers? :)
Lets create two serializers, one for user data validation (Because we don't trust the USER!) and one for multi data insert.
I haven't checked the code! But you can use it was an example...
class ShowEventSerializer(serializers.Serializer):
event_id = serializers.IntegerField()
start_date = serializers.DateField(required=True)
end_date = serializers.DateField(required=True)
time_list = serializers.ListField(
child=serializers.TimeField()
)
class Meta:
fields = ('event_id', 'start_date', 'end_date', 'time_list')
class ShowSerializer(serializers.Serializer):
date_time = serializers.DateTimeField()
class Meta:
model = Show
fields = ('event', 'date_time')
Now, with the serializers, we are going to validate the user data and then to create a json data object:
def create_show_by_datetime(self, request):
show_event_serializer = ShowEventSerializer(data=request.data)
if not show_event_serializer.is_valid():
return Response({'error': show_event_serializer.errors},status=status.HTTP_400_BAD_REQUEST)
event_id = show_event_serializer.data['event_id']
try:
event = Event.objects.get(id=event_id)
except Event.DoesNotExist:
return Response({'error': 'event with id: %s does not exist.' % event_id},status=status.HTTP_400_BAD_REQUEST)
start_date = show_event_serializer.data['start_date']
end_date = show_event_serializer.data['end_date']
time_list = show_event_serializer.data['time_list']
date_format = '%Y-%m-%d'
time_format = "%I:%M %p"
try:
datetime.strptime(start_date, date_format)
datetime.strptime(end_date, date_format)
for i in range(len(time_list)):
time = datetime.strptime(time_list[i], time_format)
except ValueError as e:
return Response(
{'error': 'Time was not in a supported format. %s' % e},
status=status.HTTP_400_BAD_REQUEST
)
delta_days = datetime.strptime(end_date, date_format).date() - datetime.strptime(start_date, date_format).date()
delta_days = delta_days.days + 1
dt = None
show_data = []
for i in range(delta_days):
day = datetime.strptime(start_date, date_format) + timedelta(days=i)
for i in range(len(time_list)):
hrs = datetime.strptime(time_list[i], time_format).hour
mins = datetime.strptime(time_list[i], time_format).minute
dt = day + timedelta(hours=hrs, minutes=mins)
show_data.append({
"event": event,
"date_time": dt
})
try:
with transaction.atomic():
show_serializer = ShowSerializer(data=show_data, many=True)
if show_serializer.is_valid():
show_serializer.save()
return Response({"data": 'Post succesfull'}, status=status.HTTP_201_CREATED)
except IntegrityError as e:
return Response(
{
'error': "event with date and time already exsits. %s-%s-%s at %s:%s" % (
dt.day, dt.month, dt.year, dt.hour, dt.minute),
'detail': str(e)
}, status=status.HTTP_400_BAD_REQUEST
So this code is basically the same as yours, with the difference of the way the objects are saved using the DRF. Look the show_data
variable.
This solution is just a different way of looking at the question.
GOOD LUCK!
http://www.django-rest-framework.org/api-guide/serializers/
http://www.django-rest-framework.org/api-guide/fields/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With