我有两个外键相连的机型,如下所示:

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}'

我想要做的是,Reservation中的turn字段获得选项choices,选项的值从1到service.counter.service是这里的外键.例如,如果Service模型中的counter为5,则Reservation中的turn字段如下所示: turn = models.PositiveIntegerField(choices=[1,2,3,4,5]).For循环显然不会起作用:). 我应该创建property字段还是Meta类? 不管怎么说,我怎么能像这样改变我的领域呢? 任何帮助都会令人感激和感激.

after one hour searching, I think for a better approach to solve this. I'v change 100 field into a Generated field so we make a query and assert it to the database, but I'm not sure how to do that? Can anyone help?

推荐答案

选项1:只有Service个已经存在,您想要创建一个完整的新Reservation,并让用户 Select Connected Service.这个选项的答案很可能在后端Django中找不到,但必须在前端处理.原因是当用户 Select 不同的连接Service时,它需要在运行中切换turn的可能 Select .

选项2:当要求用户 Select turn时,具有连接Service的初始Reservation对象已经存在.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)

上面展示了如何创建动态表单.基本上,您是在视图中预先 Select 要传递给表单的内容.然后在__init__方法中,您可以捕获它并相应地设置它.

由于您说此表单始终已绑定到对象,因此已连接到服务,因此您也可以 Select 此选项:

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)

Python相关问答推荐

如何在BeautifulSoup中链接Find()方法并处理无?

具有多个选项的计数_匹配

查找两极rame中组之间的所有差异

从numpy数组和参数创建收件箱

如何过滤包含2个指定子字符串的收件箱列名?

从groupby执行计算后创建新的子框架

Pandas—合并数据帧,在公共列上保留非空值,在另一列上保留平均值

try 将一行连接到Tensorflow中的矩阵

pyscript中的压痕问题

将JSON对象转换为Dataframe

删除marplotlib条形图上的底边

以逻辑方式获取自己的pyproject.toml依赖项

人口全部乱序 - Python—Matplotlib—映射

如何为需要初始化的具体类实现依赖反转和接口分离?

在matplotlib中重叠极 map 以创建径向龙卷风图

查找数据帧的给定列中是否存在特定值

Match-Case构造中的对象可调用性测试

普洛特利express 发布的人口普查数据失败

将Pandas DataFrame中的列名的长文本打断/换行为_STRING输出?

Django查询集-排除True值