如何在Django的同一个表中阻止外键的相同对象引用?

时间:2017-12-13 10:17:47

标签: python django django-models django-forms django-admin

我有一个拥有自己外键的模型。

models.py

class Employee(AbstractUser):
    manager = models.ForeignKey('self', on_delete=models.SET_NULL, related_name=_('manger'), null=True)

现在,当我将此模型添加到管理网站并尝试更新员工时,用户可以将自己设置为自己的管理员。因此,如果我尝试更新员工ID#1,我不希望员工ID#1显示在经理下拉列表中。

其他问题

我知道我可以添加在我的更新表单中验证此条件的clean方法,但是我不知道如何获取当前对象ID以检查管理员ID。

forms.py

class EmployeeChangeForm(UserChangeForm):

   class Meta:
        model = Employee
        fields = '__all__'

   def clean_manager(self):
        # An Employee Cannot have himself assigned as a manager

        eID = ??  # how do i get the id of Current Employee here ?
        mgr = self.cleaned_data["manager"]
        if eID == mgr:
           raise forms.ValidationError("Employee and Manger should be diffrent !!")
        return mgr

上述方法不允许当前用户阻止员工将自己设置为他的经理,但员工仍将显示在经理字段的下拉列表中。如果当前员工根本没有显示在下拉列表中,我更愿意。

有办法吗?

更新

我刚刚了解了ForeignKey.limit_choices_to,它将选择限制在相关表格的特定集合中。但是,我不知道如何将当前用户ID传递给该集合。

例如:

models.py

from django.db.models import Q

class Employee(AbstractUser):
    manager = models.ForeignKey(
      'self',
      on_delete=models.SET_NULL,
      related_name=_('manger'),
      null=True,
      limit_choices_to=~Q(id=3),
)

以上代码将我的经理选择限制在除了3之外的所有经理。但我不知道如何使这个valie动态。

我不能limit_choices_to=~Q(id=self.pk)limit_choices_to=~Q(id=self.id)

请帮忙

1 个答案:

答案 0 :(得分:1)

试试这个:

class EmployeeChangeForm(UserChangeForm):

    class Meta:
        model = Employee
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance.pk:
            self.fields['manager'].queryset = Employee.objects.exclude(
                pk=self.instance.pk,
            )

请勿忘记在ModelAdmin添加form = EmployeeChangeForm时使用该表单。