简体   繁体   中英

How to block same object reference for Foreign key in same table in Django?

I have a Model which has a self foreign key.

models.py

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

Now when i add this Model to admin site and try to update an employee users's can set themself as their own manager. So if i am trying to update employee ID #1, I dont want employee ID #1 to be displayed in the managers dropdown.

Additional Question

I know that i can add clean method that validates this condition in my Update form, however i do not know how to get the current object ID to check against manager 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

The above approach will not allow the current user to block employee from setting himself as setting as his manager however, the employee will still show in the dropdown of the manager field. I would prefer if the current employee does not show in the dropdown at all.

Is there a way to do that ?

Update:

I just learned about ForeignKey.limit_choices_to which limits the choices to a particuler set from related table. However, again i do not know how will i pass the current user id to the set.

for example:

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),
)

the above code limits my manager choices to all manager's except 3. but i dont know how to make this valie dynamic.

I cant do limit_choices_to=~Q(id=self.pk) or limit_choices_to=~Q(id=self.id)

Please help

Try this:

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,
            )

Don't forget to use the form in your ModelAdmin by adding form = EmployeeChangeForm .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM