Home > front end >  Django access manytomany field from related_name in a view
Django access manytomany field from related_name in a view

Time:12-22

I have what i think is a simple question but I am struggling to find out how it works. I get how related name works for foreign keys but with many to many fields it seems to break my brain.

I have two 3 models at play here. A User, TeamMember and Team Model as seen below.

User model is the built in django model.

#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")
    ...

Now in a view i want to access a specific users team. I thought i could do this by doing something like this:

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

However if I print member_name than it prints nothing. If I try to access any of the other fields on that model like member.members.team_lead.first_name it fails to find the team_lead field. I understand that this has a .all() attribute but i thought it was tied to the team object through the members field. So if that member matches the team it would give me the team. So I thought it might be an issue if the same member was linked to more than one team (which is possible) so i tired something like this member.members.all().first().name and i get an error that states it cannot get name from NoneType.

Is there an easy way to get the team name from a relationship like this or am i better off just doing a team query with the user?

Thanks, jAC

CodePudding user response:

First of all, I would like to point out that you are not using the related_name (and related_query_name parameters in a proper way). I think this SO post will help you to understand the concept in a better way.

So, I would change the related_name (and related_query_name) values in the Team model as below,

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"
    )
    ...

Now in a view i want to access a specific user's team.

Since the Team and TeamMember models are connected via ManyToManyField, you may have "zero or more" Teams associated with a single TeamMember

So, the following query will get you all the teams associated with a particular TeamMemeber

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

You can also iterate over the QuerySet as,

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