MultipleObjectsReturned:get()返回了多个驱动程序-返回3 [英] MultipleObjectsReturned: get() returned more than one Driver -- it returned 3
问题描述
我有一个DRF API,该API应该可以提供前端Android和IOS应用。该API具有三种类型的用户,即:驱动程序,客户端和管理员。
I have a DRF API that is supposed to feed a frontend Android and IOS app. The API has three types of users namely: Driver, Client and Admin.
该客户端应该创建预订记录并由API自动分配驱动程序。根据可用的日期和时间。每天的每一天(星期日,星期一,星期二,星期三,星期四,星期五)是一个工作日,工作时间为上午7:00至晚上9:00,工作时间包括一个小时的过渡时间。例如,上午9:00的预订将花费一个小时,因此,包括所有因素在内,结束时间将是上午10:00。许多驾驶员可以同时工作。如果用户尝试预订已选择的插槽,则应用程序应向用户提供反馈。
The client is supposed to create a booking record and get assigned a driver automatically by the API. Based on availability days and times. At the moment every day (Sun, Mon, Tue, Wed, Thu, Fri) is a working day and working hours range from 7:00 am to 9:00 pm with working hours inclusive of transition being an hour. For example, booking of 9:00am will take an hour, hence finishing time will be 10:00am, all factors inclusive. Many drivers can have work at the same time. The app should give feedback to the user if they try booking already picked slots.
目前,我的问题是从驱动程序表中循环访问现有的驱动程序,并让他们加入到预订表并一一分配。我能够为一位司机分配一份工作。但是,当我添加驱动程序时,变得很困难。某些事情我感觉不太好,我也不知道它是什么。
My problem at this time is to loop through already existing drivers from drivers table, left join them to the booking table and and assign them one by one. I was able to assign one driver a job. But when I added drivers, it became difficult. There is something I am not getting well and I do not know what it is.
这是我的模特。
""" models.py """
""" Helper function to check overlapping times """
def check_time_overlap(self, fixed_start, fixed_end, new_start, new_end):
time_overlap = False
if new_start == fixed_end or new_end == fixed_start: # edge case
time_overlap = False
elif (new_start >= fixed_start and new_start <= fixed_end) or \
(new_end >= fixed_start and new_end <= fixed_end): \
# innner limits
time_overlap = True
elif new_start <= fixed_start and new_end >= fixed_end: \
# outter limits
time_overlap = True
return time_overlap
""" Function to check overlapping bookings """
def overlapping_bookings(self):
if self.finishing_at <= self.booking_time:
raise ValidationError(
'Finishing times must be after booking times'
)
bookings = Booking.objects.filter(
booking_date=self.booking_date, driver_id=self.driver
)
if bookings.exists():
for booking in bookings:
""" Check whether date and time overlaps """
if self.check_time_overlap(
booking.booking_time, booking.finishing_at,
self.booking_time, self.finishing_at
):
""" If all drivers are allocated, raise an error \
message. """
raise ValidationError(
'All our drivers are booked at: ' +
str(booking.booking_date) + ', ' + str(
booking.booking_time) + '-' +
str(booking.finishing_at))
def save(self, *args, **kwargs):
self.calc_booking_total()
self.calc_finishing_at()
self.overlapping_bookings()
super(Booking, self).save(*args, **kwargs)
在上述模型中,我编写了一个功能来检查相同的booking_date,booking_time和finishing_at时间的重叠时间,这受 ALEXANDRE PINTO 上>> https://alexpnt.github.io/2017/ 07/15 / django-calendar /
From the above models, I have written a function to check overlapping times for the same booking_date, booking_time and finishing_at times. This is inspired by ALEXANDRE PINTO on >https://alexpnt.github.io/2017/07/15/django-calendar/
以下是序列化程序
# BOOKING SERIALIZER
# ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––#
class BookingSerializer(serializers.ModelSerializer):
package = serializers.SerializerMethodField()
vehicle_type = serializers.SerializerMethodField()
client_name = serializers.SerializerMethodField()
client_phone = serializers.SerializerMethodField()
class Meta:
model = Booking
# fields = '__all__'
exclude = ('driver',)
read_only_fields = (
'booking_total', 'booking_status',
'booked_at', 'finishing_at', 'client'
)
def get_package(self, obj):
return obj.service.package_name
def get_vehicle_type(self, obj):
return obj.service.vehicle_category.name
def get_client_name(self, obj):
return obj.client.name
def get_client_phone(self, obj):
return str(obj.client.phone)
""" Function to create booking based on authenticated client and available drivers """
def create(self, validated_data):
validated_data['client'] = self.context['request'].user
validated_data['driver'] = Driver.objects.get(active=True)
bookings = Booking.objects.create(**validated_data)
return bookings
这是我的服务器日志:
推荐答案
---------------- -------------------------------------------------- ------
以下是我为以下问题创建的解决方案。任何人都可以完善它。注意:它从功能 overlapping_bookings()
中获得帮助,以便在分配所有驱动程序后在单个日期和时间停止所有预订。这从 save()
------------------------------------------------------------------------
Below is a solution I created to the following problem. Any one can perfect it. Note: It gets help from the function overlapping_bookings()
in order to stop anymore bookings for a single date and time once all drivers are allocated. This throws in a ValidationError from overlapping_bookings()
on save()
上的 overlapping_bookings()
引发ValidationError我希望它能对某人有所帮助
I hope it helps someone
在 serializers.py
中,该函数将覆盖 ModelViewSet
create
。
In serializers.py
, the function is overriding ModelViewSet
create
.
def create(self, validated_data):
""" Function to create booking objects \
and allocate drivers automatically. """
validated_data['client'] = self.context['request'].user
""" Variable to save all drivers (querysets) from the driver \
table ordered by the booking date and time. --> maybe there is \
a better way to do it. Avoid using .get()"""
drivers = Driver.objects.filter(active=True).order_by(
'-booking__booking_date', '-booking__booking_time').all()
""" Check whether the drivers querysets (list) exists """
if drivers.exists():
""" For loop to isolate a single query set from list of \
quersets (drivers) """
for drv in drivers:
""" Condition to check for inner join query between \
driver and booking table carefully filtering them using \
booking_date and booking_time. This code is helped by \
the clean() function in models. Which after every active=True \
driver is allocated a booking, raises a ValidationError. \
It is subject to be made better. Trying to find out how it \
will throw a HttpResponse error instead."""
if Booking.objects.select_related('driver').filter(
booking_date=validated_data['booking_date'],
booking_time=validated_data['booking_time'],
).annotate(drv=F('driver__user_ptr')).exists():
continue
try:
return Booking.objects.create(driver=drv, **validated_data)
except Booking.DoesNotExist:
pass
这篇关于MultipleObjectsReturned:get()返回了多个驱动程序-返回3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!