根据日期和时间创建对象

Kak*_*kar 11 python django python-3.x django-rest-framework

我有一个活动模型,每个活动都有不同的节目.

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)
Run Code Online (Sandbox Code Playgroud)

我有另一个Ticket模型.每张票都应该是唯一的.这意味着每张票都是唯一的,并与Show和Seat相关.

class Ticket(models.Model):
    show = models.ForeignKey(Show)
    seat = models.ForeignKey(Seat)

    class Meta:
        unique_together = ('show', 'seat')
Run Code Online (Sandbox Code Playgroud)

我需要根据用户提供的开始日期和结束日期创建节目.假设这是一个JSON帖子:

{
    "event_id": 1,
    "start_date": "2018-02-16",
    "end_date": "2018-02-20",
    "time_list": ["11:00 AM", "8:00 PM"]
}
Run Code Online (Sandbox Code Playgroud)

从上面的JSON示例中,我需要创建Show start,如下所示:

# 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")
)
Run Code Online (Sandbox Code Playgroud)

现在这就是我创建Show对象的方式:

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
Run Code Online (Sandbox Code Playgroud)

但我希望有比我正在做的更优雅的方式.我正在使用python 3,django 2和django rest frameowork.如何创建显示 s的事件,并DATE_TIME基础上event_id,start_date,end_date和time_list?

Gal*_*man 6

我的方法有点不同.你在问号标签中说你正在使用django-rest-framework..那么序列化器在哪里?:)

让我们创建两个序列化程序,一个用于用户数据验证(因为我们不信任USER!),另一个用于多数据插入.

我还没检查过代码!但你可以用它作为一个例子......

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')
Run Code Online (Sandbox Code Playgroud)

现在,使用序列化器,我们将验证用户数据,然后创建一个json数据对象:

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
Run Code Online (Sandbox Code Playgroud)

因此,此代码与您的代码基本相同,使用DRF保存对象的方式不同.看看show_data变量.

这种解决方案只是一种看待问题的不同方式.

祝好运!

http://www.django-rest-framework.org/api-guide/serializers/

http://www.django-rest-framework.org/api-guide/fields/


Kry*_*ček 4

那么你的Show模型应该看起来像

from django.contrib.postgres.fields import ArrayField

class Show(models.Model):
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    board = ArrayField(
        models.TimeField(blank=True, null=True),
        size=10, # specify max array size
    )
Run Code Online (Sandbox Code Playgroud)

所以你将拥有Show指定的模型DateFields和数组TimeFields。

django 文档:数组字段、时间字段、日期字段