我有两个模型通过外键相互连接,如下所示:
class Service(models.Model):
title = models.CharField(max_length=100)
counter = models.PositiveIntegerField()
def __str__(self) -> str:
return f'{self.title}'
class Reservation(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
service = models.ForeignKey(Service, on_delete=models.CASCADE)
turn = models.GeneratedField(expression='',
output_field=models.CharField(max_length=1),
db_persist=True,)
def __str__(self) -> str:
return f'{self.user}'
我想做的是
turn
中的Reservation
字段获取选项choices
并且选择值从1到service.counter
。 service
是这里的外键。例如,如果 counter
模型中的 Service
为 5,则 turn
中的 Reservation
字段将如下所示:
turn = models.PositiveIntegerField(choices=[1,2,3,4,5])
。 for 循环显然不起作用:) .
我应该创建一个
property
字段或元类吗?我怎样才能改变我的领域?
我正在寻找更好的方法来解决这个问题。我已将
turn
字段更改为生成字段,以便我们进行查询并将其断言到数据库。我怎样才能做到这一点?
选项 1:只有
Service
已存在,您想创建一个全新的 Reservation
并让用户选择已连接的 Service
。这个选项的答案很可能在后端 django 中找不到,但必须在前端处理。原因是,当用户选择不同的连接的 turn
时,需要动态切换 Service
的可能选择。
选项 2:当要求用户选择
Reservation
时,初始 Service
- 已连接 turn
的对象已存在。这可以通过 django 来完成。但不在 models.py 级别上。这个逻辑必须转到forms.py。我们需要一个模型表单,只需要填充 turn
字段。
class ReservationForm(forms.ModelForm):
class Meta:
model = Reservation
fields = ['turn']
widgets = {
'turn': forms.Select(), # Set the widget for the 'turn' field to Select
}
def __init__(self, *args, **kwargs):
service_instance = kwargs.pop('service_instance', None)
super(ReservationForm, self).__init__(*args, **kwargs)
if service_instance:
# Set the choices for the 'turn' field based on the service instance's counter
self.fields['turn'].choices = [(i, i) for i in range(service_instance.counter + 1)]
else:
# If no service instance is provided, default to an empty list
self.fields['turn'].choices = []
# views.py
service_instance = Service.objects.get(id=service_id)
form = ReservationForm(service_instance=service_instance)
上面展示了如何制作动态表单。基本上,您在视图中预先选择要传递给表单的内容。然后在
__init__
方法中捕获它并进行相应的设置。
既然你说这个表单总是已经绑定到一个对象,因此已经连接到一个服务,你也可以选择这个选项:
class ReservationForm(forms.ModelForm):
class Meta:
model = Reservation
fields = ['turn']
widgets = {
'turn': forms.Select(), # Set the widget for the 'turn' field to Select
}
def __init__(self, *args, **kwargs):
super(ReservationForm, self).__init__(*args, **kwargs)
# next line checks if an object is already connected to the form and a service connected
service_id = self.data.get('service') if self.is_bound else None
if service_id:
try:
service_instance = Service.objects.get(id=service_id)
# Set the choices for the 'turn' field based on the service instance's counter
self.fields['turn'].choices = [(i, i) for i in range(service_instance.counter + 1)]
except Service.DoesNotExist:
# If the service does not exist, default to an empty list
self.fields['turn'].choices = []
else:
# If no service ID is provided, default to an empty list
self.fields['turn'].choices = []
# views.py
# here you need to pass an instance to the form
form = ReservationForm(request.POST, instance=Reservation.objects.get(id=1)