djangodjango-modelsdjango-viewsdjango-related-manager

Django access manytomany field from related_name in a view


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


Solution

  • 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)