Django доступ к полю manytomany из related_name в представлении

У меня есть, как мне кажется, простой вопрос, но я пытаюсь понять, как он работает. Я понял, как работает связанное имя для внешних ключей, но в случае со многими полями это, кажется, ломает мой мозг.

У меня есть две 3 модели. Модель пользователя, модель члена команды и модель команды, как показано ниже.

Модель пользователя - это встроенная модель django.

#TeamMember Model
class TeamMember(models.Model):
    member = models.ForeignKey(User, on_delete=models.SET(get_default_team_member), verbose_name='Member Name', related_name="team_members")
    ...

#Team Model
class Team(models.Model):
    name = models.CharField(max_length=50)
    manager = models.ForeignKey(TeamMember, on_delete=models.SET_NULL, related_name="managers", null=True, blank=True)
    team_lead = models.ForeignKey(TeamMember, on_delete=models.SET_NULL, related_name="tls", null=True, blank=True)
    tps = models.ForeignKey(TeamMember, on_delete=models.SET_NULL, related_name="tps",  null=True, blank=True)
    members = models.ManyToManyField(TeamMember, blank=True, related_name="members")
    ...

Теперь в представлении я хочу получить доступ к команде конкретного пользователя. Я думал, что смогу сделать это, выполнив примерно следующее:

member = TeamMember.objects.get(pk=1)
member_team = member.members.name

Однако если я печатаю member_name, то ничего не выводится. Если я пытаюсь получить доступ к любому из других полей этой модели, например member.members.team_lead.first_name, то не удается найти поле team_lead. Я понимаю, что оно имеет атрибут .all(), но я думал, что оно связано с объектом команды через поле members. Таким образом, если этот член соответствует команде, то это даст мне команду. Поэтому я подумал, что это может быть проблемой, если один и тот же член будет связан с несколькими командами (что возможно), поэтому я устанавил что-то вроде этого member.members.all().first().name и получил ошибку, в которой говорится, что он не может получить имя из NoneType.

Есть ли простой способ получить название команды из такого отношения или лучше просто сделать запрос команды к пользователю?

Спасибо, jAC

Прежде всего, я хотел бы отметить, что вы не используете параметры related_namerelated_query_name правильным образом). Я думаю, что этот пост SO поможет вам лучше понять концепцию.

Итак, я бы изменил значения related_namerelated_query_name) в модели Team следующим образом,

class Team(models.Model):
    name = models.CharField(max_length=50)
    manager = models.ForeignKey(
        TeamMember,
        on_delete=models.SET_NULL,
        related_name="teams",
        related_query_name="team",
        null=True,
        blank=True,
    )
    team_lead = models.ForeignKey(
        TeamMember,
        on_delete=models.SET_NULL,
        related_name="teams",
        related_query_name="team",
        null=True,
        blank=True,
    )
    tps = models.ForeignKey(
        TeamMember,
        on_delete=models.SET_NULL,
        related_name="teams",
        related_query_name="team",
        null=True,
        blank=True,
    )
    members = models.ManyToManyField(
        TeamMember, blank=True, related_name="teams", related_query_name="team"
    )
    ...

Теперь в представлении я хочу получить доступ к команде конкретного пользователя.

Поскольку модели Team и TeamMember связаны через ManyToManyField, у вас может быть "ноль или более" Team, связанных с одним TeamMember

Итак, следующий запрос даст вам все команды, связанные с определенным TeamMemeber

team_member = TeamMember.objects.get(pk=1)
all_teams = team_member.teams.all()

Вы также можете выполнять итерации по QuerySet как,

team_member = TeamMember.objects.get(pk=1)
for team in team_member.teams.all():
    print(team.name)

Для тех, кому интересно, то, что я сделал по совету JPG, было вариантом цикла for loop

team_member = TeamMember.objects.get(pk=1)
teams = [t.name for t in team_member.members.all()]

Лично мне все равно, какую команду я получу, так как в данном случае мне нужно просто передать команду, даже если ее нет. Поэтому я просто использую team = team[0] if teams.count() > 0 else "No team"

Вернуться на верх