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_name
(и related_query_name
правильным образом). Я думаю, что этот пост SO поможет вам лучше понять концепцию.
Итак, я бы изменил значения related_name
(и related_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"