Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 基于日期和时间创建对象_Python_Django_Python 3.x_Django Rest Framework - Fatal编程技术网

Python 基于日期和时间创建对象

Python 基于日期和时间创建对象,python,django,python-3.x,django-rest-framework,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) 我有另一种票型。每张票都应该是唯

我有一个活动模型,每个活动都有不同的表演

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)
我有另一种票型。每张票都应该是唯一的。这意味着每张票都是独一无二的,并且与一场演出和一个座位有关

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

    class Meta:
        unique_together = ('show', 'seat')
我需要根据用户提供的开始日期和结束日期创建节目。假设这是一篇JSON文章:

{
    "event_id": 1,
    "start_date": "2018-02-16",
    "end_date": "2018-02-20",
    "time_list": ["11:00 AM", "8:00 PM"]
}
根据上面的JSON示例,我需要创建如下开头的Show:

# 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")
)
现在,这就是我创建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

但我希望有比我现在做的更优雅的方式。我正在使用python 3、django 2和django rest框架工作。如何根据
事件id
开始日期
结束日期
时间列表
创建带有事件的显示和日期时间?

那么您的
显示
模型应该是这样的

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
    )
因此,您将使用指定的
日期字段和
时间字段数组创建模型
Show


django docs:,

我将离开验证部分,只关注从给定数据生成
Show
对象:

data = request.data

date_format = '%Y-%m-%d'
time_format = "%I:%M %p"
show_time_format = f"{date_format} {time_format}"

# get the total number of days by parsing start and end dates
start_date = datetime.strptime(data['start_date'], date_format)
end_date = datetime.strptime(data['end_date'], date_format)
total_days = (end_date - start_date).days + 1

# Get the timings for the first day.
# We will use this to generate the timings for the rest of the days.
first_day_timings = [
    datetime.strptime(f"{data['start_date']} {show_time}", show_time_format)
    for show_time in data['time_list']
]

# generate all show objects using list comprehension and bulk create later
show_objects = [
    Show(event=event, date_time=first_day_timing + timedelta(days=day_cnt))
    for day_cnt in range(total_days)
    for first_day_timing in first_day_timings
]

Show.objects.bulk_create(show_objects)
对现有代码所做的增强:

  • 减少了实例数—解析日期/时间和计算小时/分钟
  • 使用列表理解生成显示对象和批量创建,而不是在事务中一次创建一个对象

  • datetime库中有一些工具可以为您提供一种更简化的生成时间的方法。您可以使用
    toordinal
    将日期转换为整数,使用
    fromordinal
    将整数转换回日期;这是创建一系列日期的好方法。您可以使用
    combine
    date
    对象和
    time
    对象合并为
    datetime
    。我将创建以下函数:

    from datetime import datetime, date
    
    def get_showtimes(post):
        start = datetime.strptime(post['start_date'], '%Y-%m-%d')
        end = datetime.strptime(post['end_date'], '%Y-%m-%d')
        times = [datetime.strptime(t, '%I:%M %p').time() for t in post['time_list']]
        for ordinal in range(start.toordinal(), end.toordinal() + 1):
            date = date.fromordinal(date)
            for time in times:
                yield datetime.combine(date, time)
    
    然后,在代码中,将第二个
    try:except:
    块及其后面的内容替换为:

    try:
        showtimes = list(get_showtimes(post))
    except ValueError as e:
        return Response(
            {'error': 'Time was not in a supported format. %s' % e},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    try:
        with transaction.atomic():
            for showtime in showtimes:
                show = Show.objects.create(event=event, date_time=showtime)
    except IntegrityError as e:
        # etc.
    

    我的方法有点不同。您在问号中说您正在使用
    django rest框架
    。。那么序列化程序在哪里呢?:)

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

    我还没有检查密码!但你可以用它作为一个例子

    现在,使用序列化程序,我们将验证用户数据,然后创建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
    
    因此,这段代码与您的代码基本相同,只是使用DRF保存对象的方式不同。查看
    show_data
    变量

    这个解决方案只是另一种看待问题的方式

    祝你好运


    如何保存过账数据???没有足够的字段将数据映射到DB@Ananthu可能使用for循环?在有效负载中,您正在传递
    开始日期
    结束日期
    时间列表
    。你能解释一下为什么吗?@JerinterGeorge我已经更新了这个问题。请看一看。实际上,我还有另一种票型。每张票都应该是唯一的。这意味着每张票都与一场演出和一个座位有关。因此,我认为最好是有一个单独的节目。我已经更新了问题,请看一下。
    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