【发布时间】:2021-09-29 18:10:19
【问题描述】:
我有 2 组 5 名员工。在每个组中,其中一名员工是该组的主管。
在创建视图中,一旦主管字段被填充,我希望员工外键字段仅显示属于该主管的员工。
最好根据用户(主管)显示适当的员工,而不必先填充主管字段。
我已经尝试过模型表单来尝试适当地修改员工外键字段查询集,显然无济于事。请帮忙!
代码如下:
class Instruction(models.Model):
supervisor = models.ForeignKey(
Profile, on_delete=models.CASCADE,
related_name="supervisorinstructions"
)
employee = models.ForeignKey(
Profile, on_delete=models.CASCADE,
related_name="employeeinstructions"
)
instruction = models.CharField(max_length=300)
def __str__(self):
return f"{self.instruction}"
def get_absolute_url(self):
return reverse("myapp:instructiondetail", kwargs={"pk": self.pk})
class InstructionCreate(CreateView):
model = models.Instruction
fields = [
"supervisor",
"employee",
"instruction",
]
template_name = "myapp/instruction_create_form.html"
更多信息。
更多上下文(请原谅双关语)...
我已经能够获得向特定主管汇报的员工名单。
每个员工只向一位主管汇报,因此这些员工都不会出现在向另一位主管汇报的任何其他员工列表中。
据此,我能够放置一个链接到(模板)视图,其中上下文是选定的员工,并使用上下文生成特定于该员工的报告,如下所示:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
profile = models.Profile.objects.get(**kwargs)
context["profile"] = profile
employee = profile.employee
context["employee"] = employee
supervisor = profile.supervisor
context["supervisor"] = supervisor
# report queries
return context
由于只有该主管可以生成该报告,因此也应该只有该主管能够为员工创建指令,甚至无需在表单中指定谁(主管)为其创建指令谁(员工),以及从上下文数据中自动设置我的模型所需的适当属性。
这是我有问题的地方。我正在使用 CBV,并且只有一名主管 可以为员工创建对象。
当主管想要为员工创建指令时,我希望能够使用上下文(就像在报告中所做的那样)来确定指令是针对谁以及谁在给出指令。
目前,当创建表单打开时,无论是否确定主管,所有员工都会出现,从而使主管可以为其他主管的员工创建指令,这就是我试图阻止的。
我在 Django 中太新了,无法自己解决这个问题。在我的新手看来,应该可以使用上下文中的主管和员工详细信息预先填充创建表单,从而消除下拉问题。
新建,按要求的员工模型---`
class Profile(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name="userprofiles")
employee = models.ForeignKey(
"self", on_delete=models.CASCADE, null=True, blank=True,
related_name="employeeprofiles",
)
supervisor1 = models.ForeignKey(
"self", on_delete=models.CASCADE, null=True, blank=True,
related_name="supervisorprofiles",
)
def __str__(self):
return f"{self.user}"
def get_absolute_url(self):
return reverse("myapp:profiledetail", kwargs={"pk": self.pk})`
更正了最后一个模型的名称,它是 Employee,但应该是 Profile,如 Instruction 模型中所示。
希望这是答案:
class InstructionCreateForm(ModelForm):
class Meta:
model = models.Instruction
fields = ["supervisor", "employee", "instruction"]
def clean(self):
cleaned_data = super(InstructionCreateForm, self).clean()
supervisor = cleaned_data.get('supervisor')
employee = cleaned_data.get('employee')
# check if the supervisor is the employee's supervisor and raise error if not
if supervisor != models.Profile.objects.filter(employee=employee).supervisor:
self.add_error(None, ValidationError('The employee is not your direct subordinate.'))
return cleaned_data
class InstructionCreate(CreateView):
model = models.Instruction
template_name = "internalcontrol/instruction_create_form.html"
form_class = forms.InstructionCreateForm
成功了!但仅在此更改之后:
我替换了if supervisor != models.Profile.objects.filter(employee=employee).supervisor:
if employee != models.Profile.objects.filter(employee=employee, supervisor=supervisor):
让它工作。
CBV 创建模板:
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<div class="btn-group">
<input type="submit" class="btn btn-primary btn-sm" value="Add">
<a href="{% url 'company:instructionlist' %}" class="btn btn-secondary btn-sm">List</a>
</div>
</form>
【问题讨论】:
-
很遗憾没有,阿卜杜勒。我添加了更多信息来阐明我需要的帮助。
-
啊,我误解了,因为“一旦主管字段被填充,我希望员工外键字段只显示属于该主管的员工。”但是相反,您希望主管甚至不是该表单上的字段,而只想显示过滤后的选择?见How do I filter ForeignKey choices in a Django ModelForm?
-
你会添加 Supervisor 和 Employee 模型吗?
-
@KayaKwinana
ModelChoiceField是外键的默认字段(默认为您提供选择输入),您希望将这些选择限制为当前主管下的员工,该链接问题会显示给您如何过滤表单选择...