Django - 如何为模型的外键创建表单?

26 投票
1 回答
46375 浏览
提问于 2025-04-16 16:03

我想做的是这样的。我在想有没有人能给我一些好的建议:

这是我的 models.py 文件:

class Color(models.Model):
    name = models.CharField(...

class Speed(models.Model):
    name = models.CharField(...

class Dog(models.Model):
    name = models.CharField(...
    color = models.ForeignKey(Color...
    speed = models.ForeignKey(Speed...

class DogRequest(models.Model):
    dog = models.ForeignKey(Dog...
    request_time = models.DateTimeField()

现在我想要一个页面,用户可以在上面输入或编辑一个 DogRequest,但表单应该长这样:

Enter Dog Request:
---------------------
color (dropdown V)
speed (dropdown V)
|save|

那么我该如何在视图中设计这个表单呢?问题是用户输入的是狗的属性,而不是一只具体的狗。所以我需要根据用户输入的内容来查找或创建一条狗的记录。

到目前为止,我尝试过这样的做法:

class DogRequestForm(ModelForm):
    class Meta:
        model = DogRequest
        fields = ('request_time','color','speed')
    color = forms.ModelChoiceField(queryset=Color.objects.all())
    speed = forms.ModelChoiceField(queryset=Speed.objects.all())

假设这能正常工作,那我该把代码放在哪里,以便根据用户输入的颜色和速度来确定使用(或创建)哪条狗的记录呢?还有,我该如何从 DogRequest 中填充这个表单呢?

1 个回答

22

我觉得在这里你不需要用ModelForm。因为在调用is_valid()之前,你不会找到或者创建狗的对象,所以它永远不会有效。

相反,我建议你使用一个普通的表单,然后重写DogRequest的保存方法,去查找或创建狗的对象。

更新:针对评论中的后续问题,我没有测试过这个,但类似的方式应该是可行的。

class DogRequestForm(forms.Form):
    id = forms.IntegerField(required=False, widget=forms.HiddenInput())
    color = forms.ModelChoiceField(queryset=Color.objects.all())
    speed = forms.ModelChoiceField(queryset=Speed.objects.all())

然后当你为编辑视图创建这个表单的实例时,你需要用类似这样的方式来实例化它:

data = {
    'id': dog_request_id,
    'color': dog_color,
    'speed': dog_speed,
}
form = DogRequestForm(data)

在这里,你需要从现有的DogRequest对象中填充当前的dog_request_iddog_colordog_speed

撰写回答