[英]How to display relationship with back reference at django template through User?
我有这样的模型
class Employee(models.Model):
"""Employee information."""
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='employee', unique=True)
position = models.CharField("current position in a company", max_length=64, blank=True)
birth_date = models.DateField("date of birth", null=True)
skills = models.ManyToManyField(
Technology, through="Skill", verbose_name="skills", blank=True)
class Technology(models.Model):
"""Technologies."""
name = models.CharField('technology name', max_length=32, unique=True)
class Skill(models.Model):
"""Information about an employee's skills."""
LEVELS = (
('basic', 'Basic'),
('intermediate', 'Intermediate'),
('advanced', 'Advanced'),
('expert', 'Expert'),
)
employee = models.ForeignKey(
Employee, on_delete=models.CASCADE, related_name="employee_skills")
technology = models.ForeignKey(Technology, on_delete=models.CASCADE)
start_date = models.DateField(
verbose_name='Works with since:')
level = models.CharField("level", max_length=64, choices=LEVELS)
而且我不明白为什么我的模板代码不起作用
template.html
{{ user.employee.position }}
{{ user.employee.birth_date }}
{{ user.employee.summary }}
{% for i in user.employee.skills.all %}
{{ i.technology.name }}
{{ i.level }}
{% endfor %}
我绝对看不到。 所有型号都可以在adminpanel上看到。 然后我使用诸如
class AccountView(TemplateView):
template_name = "profile.html"
def get_context_data(self, **kwargs):
context = super(AccountView, self).get_context_data(**kwargs)
context['skills'] =
Skill.objects.filter(employee__user=self.request.user)
return context
然后一切正常。
您的Employee模型目前与用户具有一对多关系
class Employee(models.Model):
"""Employee information."""
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='employee', unique=True)
根据您的评论,您需要一对一的关系,因此您需要将其更改为使用OneToOneField
而不是ForeignKey
从概念上讲,这类似于具有unique = True的ForeignKey,但是关系的“反向”侧将直接返回单个对象。
建模有问题。 您应该在Employee
和User
之间使用OneToOneField
。 本质上, OneToOneField
是唯一的 ForeignKey
。 但是,它将更改一些逻辑,例如user.employee
将访问相关的Employee
对象,而不是Employee
的QuerySet
:
class Employee(models.Model):
# ...
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='employee'
)
# ...
AccountView
,在AccountView
,您将'skills'
与该员工的技能进行了统一:
class AccountView(TemplateView):
template_name = "profile.html"
def get_context_data(self, **kwargs):
context = super(AccountView, self).get_context_data(**kwargs)
context.update(
skills=Skill.objects.filter(employee__user=self.request.user).select_related('technology')
)
return context
您可能希望在此处使用.select_related(..)
来防止所谓的“ N + 1问题 ”,在此情况下,每种技能都会产生一个额外的查询。
因此,您可以通过以下方式呈现技能:
{% for skill in skills %}
{{ skill.technology.name }}
{{ skill.level }}
{% endfor %}
或者您可以通过以下方式访问:
{% for skill in request.user.employee.employee_skills.all %}
{{ skill.technology.name }}
{{ skill.level }}
{% endfor %}
尽管上述方法不太安全,但因为User
可能没有相关的Employee
对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.