繁体   English   中英

如何通过用户在Django模板上显示与反向引用的关系?

[英]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,但是关系的“反向”侧将直接返回单个对象。

建模有问题。 您应该在EmployeeUser之间使用OneToOneField 本质上, OneToOneField唯一的 ForeignKey 但是,它将更改一些逻辑,例如user.employee将访问相关的Employee对象,而不是EmployeeQuerySet

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.

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