Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create objects based on date and time

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?

like image 683
Kakar Avatar asked Feb 15 '18 06:02

Kakar


People also ask

How do you create a date object?

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.

How do you create a date object in Python?

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.

What is a date object in Python?

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.

What is a date object in JavaScript?

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.


1 Answers

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/

like image 94
Gal Silberman Avatar answered Oct 16 '22 09:10

Gal Silberman