通过外键Django从一个字段到另一个字段创建一个选择列表

问题描述 投票:0回答:1

我有两个模型通过外键相互连接,如下所示:

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
字段更改为生成字段,以便我们进行查询并将其断言到数据库。我怎样才能做到这一点?

python django django-rest-framework
1个回答
1
投票

选项 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)
© www.soinside.com 2019 - 2024. All rights reserved.