0

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

jAC
  • 3,155
  • 3
  • 18
  • 29

2 Answers2

1

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)
JPG
  • 82,442
  • 19
  • 127
  • 206
  • Hey @JPG thanks for the extra details. I don't have need to do this that much that post is very helpful! Thanks so much! – jAC Dec 22 '21 at 13:25
  • Actually i do not think i am using the related_name wrong. If i change it to your suggesting it fails saying i cannot use the same related name... However, the rest of your advice helped me fix it. – jAC Dec 22 '21 at 16:04
  • You were ***using*** the correct way (programmatically), but, logically, it is wrong. – JPG Dec 22 '21 at 17:15
  • Not sure how it was wrong as your example above doesn't work programmatically. Can you elaborate? Just curious what I should be doing instead of that. – jAC Dec 23 '21 at 21:41
0

For anyone wondering what I did based on JPG's advice was the for loop option

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

I personally do not care which team i get as my need in this case is just to pass a team through even if it is none. So i just use team = team[0] if teams.count() > 0 else "No team"

jAC
  • 3,155
  • 3
  • 18
  • 29