Django模型关系

4
我有这些模型。
class Event(models.Model):
    name = models.CharField(max_length = 50)

class DriverClass(models.Model):
    name = models.CharField(max_length = 20)
    event = models.ForeignKey(Event)

class Driver(models.Model):
    name = models.CharField(max_length = 50)
    event = models.ForeignKey(Event)
    driverclass = models.ForeignKey(DriverClass)

一个事件应该有一定数量的DriverClassDriver选择。目前的问题是,一个Driver只与一个DriverClass和一个Event相连。所以当我在django admin中为驱动程序选择一个DriverClass时,我可以从所有的DriverClass中选择。我不确定是否需要更改我的模型才能实现我想要的功能,或者是否只需更改DriverModelAdmin类以仅显示正确的事件。正确的操作步骤是什么?

DriverDriverClass中选择的筛选条件是什么? - karthikr
驱动程序与一个事件相关联,然后是该事件的驱动程序类。 - Martol1ni
1
我认为你的模型构建有问题。就像这样,你有一个“事件”,一个事件可以有许多“驱动程序类”。很好。因此,“驱动程序类”已经与事件相关联,因此与某个“驱动程序类”相关联的“驱动程序”已经连接到事件中了,不是吗?我仍然不明白你想要什么。 - Games Brainiac
你说得对,我的模型可能构建得不太好。我可以取消Driver->Event的链接,但仍然保留后面的连接,但在我看来,这是一种非常奇怪的做法。我只是想知道在Django中将多个模型绑定在一起的惯例是什么。 - Martol1ni
2个回答

4

您应该指定一个自定义的ModelForm,以更改driverclass字段的查询集,并将其添加到ModelAdmin中:

class DriverForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(DriverForm, self).__init__(*args, **kwargs)
        if self.instance.event: 
            # this form has an event specified in either instance, initial or data
            self.fields['driverclass'].queryset = DriverClass.objects.filter(event=self.instance.event)

class DriverAdmin(admin.ModelAdmin):
    form = DriverForm

需要注意的是,当您更改 Event 时,DriverClass 的选项直到提交表单后才会更新。表单将抛出一个验证错误,返回的表单将具有正确的选择。要更改此行为,需要通过Javascript进行Ajax请求和动态更新。


我可以这样做,这是常规做法吗? - Martol1ni
@Martol1ni 我猜是这样,覆盖表单的__init__方法以实现此类动态的每个实例更改是常规做法,而我认为这正是字段的queryset属性所用之处。 - knbk
@Martol1ni 如果您对此答案感到满意,请接受并关闭此问题。 - knbk
当更改DriverClass实例的事件时,驱动程序会发生什么情况? 驱动程序的“事件”是否应相应更改,驱动程序的“driverclass”是否应设置为适合其“事件”的驱动程序,还是应删除驱动程序,因为它没有合法的driverclass,事件组合? @Martol1ni - Chris Wesseling
好的观点。回顾这个问题,DriverClass是唯一属于一个Event的吗?我想这与赛车有关,一个DriverClass应该与Event具有多对多的关系,不管怎样,当DriverClass被更改或删除时,您应该确定您想要什么。 - knbk
显示剩余2条评论

0

智多星游戏是正确的。如果您坚持在驱动程序上拥有事件属性,那么这就是您可以对其进行建模的方式:

class Event(models.Model):
    name = models.CharField(max_length = 50)

class DriverClass(models.Model):
    name = models.CharField(max_length = 20)
    event = models.ForeignKey(Event)

class Driver(models.Model):
    name = models.CharField(max_length = 50)
    driverclass = models.ForeignKey(DriverClass)

    @property
    def event(self):
        return self.driverclass.event

刚刚阅读了Django:ForeignKey limit_choices_to to equal current object's client,发现你想要的方式实际上是“奇怪的方式”。按照你想要的方式,参考完整性无法得到保证。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接