Django:多对一字段和数据完整性

时间:2010-05-03 22:21:17

标签: django django-models foreign-keys orm foreign-key-relationship

假设我有一个运行库存系统的人员。每个人都有一些汽车,每辆汽车都有很多零件(数千,比方说)。

Person,Bob,使用Django表单来创建Car。现在,鲍勃去创建一些零件。只有在形式级别,Django知道部件属于某个特定的Car,并且Parts.ForeignKey(Car)字段应该只有特定的Car作为选择。创建一个Part时,你必须弄乱表单的构造函数或类似的东西,以便将Cars的选择限制为只有Bob拥有的汽车。

在表单级别强制执行此所有权似乎并不合适或安全。首先,似乎其他用户的汽车必须是除了车主之外的任何人都无法进入的;目前,只有固体表格编程可以防止任何人查看任何其他人的车!其次,通过以这种方式修改构造函数来处理问题似乎很草率。您对此有何看法,有没有办法强制执行此操作?

1 个答案:

答案 0 :(得分:1)

首先,这部分应该发生在您知道谁是当前用户的级别。 在Django中,没有什么比全局request.user更好的了,所以你需要检查一下你有一个请求对象或将它作为一个参数传递。

实现您要求的一种方法是使用自定义管理器。对于Car类,您可以使用

class CarManager(models.Manager):
    def for_user(self, user):
        return super(CarManager, self).get_query_set().filter(creator=user)

您可能还希望覆盖默认管理器,并且它的默认方法仅允许此方法。

对于第二部分,如果你不喜欢它,你不需要修改构造函数。但是修改它们可以确保您无法在没有登录用户的情况下创建表单。另一种方法是使用ModelChoiceField并在视图中覆盖它的queryset attr:

form.car.queryset = Car.objects.for_user(request.user)

但这种方法容易出错。您应该按照以下方式修改表单构造函数:

class PartForm(forms.ModelForm):
    def __init__(self,user,*args,**kwargs):
        super (PartForm,self ).__init__(*args,**kwargs)
        self.fields['car'].queryset = Car.objects.for_user(user)

希望这有帮助。