django - 多对多关系问题
django - Many To Many relationship issue
我在 django 工作,正在为用户规划一个游乐设施数据库。
每个行程可以有多个用户(乘客),以及多个中间目的地 在里面。
此外,每个 Destination 可以在多个 Rides 中,每个 User (乘客)可以在多个 乘车(加班)。
此外,对于每个 行程,只有一个 最终目的地,并且只有一个 driver(也是 用户).
这是我的代码:
def get_image_path(models.Model):
return os.path.join('photos',str(instance.id),filename)
class UserProfile(models.Model):
user=models.OneToOneField(User)
phone_number=models.CharField(max_length=12)
profile_picture=models.ImageField(upload_to=get_image_path, black=True, null=True)
class Ride(models.Model):
driver=models.ForeignKey(UserProfile, related_name="r_driver")
destination=models.ForeignKey(Destination, related_name="r_final_destination")
leaving_time=models.DateTimeField()
num_of_spots=models.IntergerField()
passengers=models.ManyToMany(UserProfile, related_name="r_passengers")
mid_destinations=models.ManyToMany(Destination, related_name="r_mid_destinations")
class Destination(models.Model):
name=models.CharField(max_length=30)
问题是 - 当用户添加行程时,我想要driver、目的地和mid_destinations 和由 User 设置的其余字段(driver 是 User 添加行程),Except passengers 字段。我希望其他 Users 将自己添加到行程中,因此在创建行程时,用户 (driver) 不必设置乘客。
我该怎么做?还有关于模型的其他建议?
关于问题的第一部分
The Issue is - when a User adds a Ride, I want the driver, destination
and mid_destinations and the rest of the fields to be set by the User
(the driver is the User adding the Ride), Except for the passengers
field.
django.forms方式
您只需要一个自定义表单并手动处理 driver
字段。像这样:
class DriverRideForm(forms.ModelForm):
class Meta:
model = Ride
exclude = ('driver', 'passengers', )
然后在 view
中 request.user
是 driver
form = DriverRideForm(request.POST)
if form.is_valid():
ride = form.save(commit=False)
ride.driver = request.user.userprofile
ride.save()
django-rest-framework 方式
可以,但您可能不想从 serializer
字段中排除 driver
。这是因为通常每个 ViewSet
只使用一个序列化程序,因此您需要 return 那个字段给 API 的消费者。
所以你有两个选择:
将 driver 字段更改为 read-only
并勾选 perform_create
:
class RideSerializer(serializers.ModelSerializer):
class Meta:
model = Ride
read_only_fields = ('driver', 'passengers')
#inside your RideViewSet
def perform_create(self, serializer):
serializer.save(driver=self.request.user.userprofile)
在不更改序列化器的情况下执行.create
之前将driver
字段添加到request.data
。
#inside your RideViewSet
def create(self, request, *args, **kwargs):
request.data['driver'] = self.request.user.userprofile
return super(RideViewSet, self).create(request, *args, **kwargs)
用户如何使用 read-only passengers
字段添加自己?
我可能会使用自定义端点(@detail_route
)。像这样:
class RideViewSet(...):
#...
@detail_route(methods=['post'])
def attach(self, request, pk=None):
ride = self.get_object()
ride.passengers.add(request.user.userprofile)
return Response(self.get_serializer(ride).data)
这样 POST-ing 在 url
就像 /api/rides/<id>/attach/
将把登录的 request.user
添加到 ride.passengers
.
关于问题的第二部分
any other suggestions about the models?
我觉得你的模型结构很好。我只能想到,将来你可能需要更多关于关系的元数据,所以现在可能是准备一些 Intermediate Models
的好时机,比如:
class Ride(models.Model):
# ...
passengers=models.ManyToMany(UserProfile, through='RideSeat', related_name="r_passengers")
mid_destinations=models.ManyToMany(Destination, through='RideMidDestination', related_name="r_mid_destinations")
class RideSeat(models.Model):
ride = models.ForeignKey(Ride)
passenger = models.ForeignKey(UserProfile)
seat_number = models.IntegerField()
class RideMidDestination(models.Model):
ride = models.ForeignKey(Ride)
destination = models.ForeignKey(Destination)
arrival_time = models.DateTimeField()
我在 django 工作,正在为用户规划一个游乐设施数据库。
每个行程可以有多个用户(乘客),以及多个中间目的地 在里面。 此外,每个 Destination 可以在多个 Rides 中,每个 User (乘客)可以在多个 乘车(加班)。
此外,对于每个 行程,只有一个 最终目的地,并且只有一个 driver(也是 用户).
这是我的代码:
def get_image_path(models.Model):
return os.path.join('photos',str(instance.id),filename)
class UserProfile(models.Model):
user=models.OneToOneField(User)
phone_number=models.CharField(max_length=12)
profile_picture=models.ImageField(upload_to=get_image_path, black=True, null=True)
class Ride(models.Model):
driver=models.ForeignKey(UserProfile, related_name="r_driver")
destination=models.ForeignKey(Destination, related_name="r_final_destination")
leaving_time=models.DateTimeField()
num_of_spots=models.IntergerField()
passengers=models.ManyToMany(UserProfile, related_name="r_passengers")
mid_destinations=models.ManyToMany(Destination, related_name="r_mid_destinations")
class Destination(models.Model):
name=models.CharField(max_length=30)
问题是 - 当用户添加行程时,我想要driver、目的地和mid_destinations 和由 User 设置的其余字段(driver 是 User 添加行程),Except passengers 字段。我希望其他 Users 将自己添加到行程中,因此在创建行程时,用户 (driver) 不必设置乘客。
我该怎么做?还有关于模型的其他建议?
关于问题的第一部分
The Issue is - when a User adds a Ride, I want the driver, destination and mid_destinations and the rest of the fields to be set by the User (the driver is the User adding the Ride), Except for the passengers field.
django.forms方式
您只需要一个自定义表单并手动处理 driver
字段。像这样:
class DriverRideForm(forms.ModelForm):
class Meta:
model = Ride
exclude = ('driver', 'passengers', )
然后在 view
中 request.user
是 driver
form = DriverRideForm(request.POST)
if form.is_valid():
ride = form.save(commit=False)
ride.driver = request.user.userprofile
ride.save()
django-rest-framework 方式
可以,但您可能不想从 serializer
字段中排除 driver
。这是因为通常每个 ViewSet
只使用一个序列化程序,因此您需要 return 那个字段给 API 的消费者。
所以你有两个选择:
将 driver 字段更改为
read-only
并勾选perform_create
:class RideSerializer(serializers.ModelSerializer): class Meta: model = Ride read_only_fields = ('driver', 'passengers') #inside your RideViewSet def perform_create(self, serializer): serializer.save(driver=self.request.user.userprofile)
在不更改序列化器的情况下执行
.create
之前将driver
字段添加到request.data
。#inside your RideViewSet def create(self, request, *args, **kwargs): request.data['driver'] = self.request.user.userprofile return super(RideViewSet, self).create(request, *args, **kwargs)
用户如何使用 read-only passengers
字段添加自己?
我可能会使用自定义端点(@detail_route
)。像这样:
class RideViewSet(...):
#...
@detail_route(methods=['post'])
def attach(self, request, pk=None):
ride = self.get_object()
ride.passengers.add(request.user.userprofile)
return Response(self.get_serializer(ride).data)
这样 POST-ing 在 url
就像 /api/rides/<id>/attach/
将把登录的 request.user
添加到 ride.passengers
.
关于问题的第二部分
any other suggestions about the models?
我觉得你的模型结构很好。我只能想到,将来你可能需要更多关于关系的元数据,所以现在可能是准备一些 Intermediate Models
的好时机,比如:
class Ride(models.Model):
# ...
passengers=models.ManyToMany(UserProfile, through='RideSeat', related_name="r_passengers")
mid_destinations=models.ManyToMany(Destination, through='RideMidDestination', related_name="r_mid_destinations")
class RideSeat(models.Model):
ride = models.ForeignKey(Ride)
passenger = models.ForeignKey(UserProfile)
seat_number = models.IntegerField()
class RideMidDestination(models.Model):
ride = models.ForeignKey(Ride)
destination = models.ForeignKey(Destination)
arrival_time = models.DateTimeField()