Pi Ca
Pi Ca

Reputation: 19

How to access to a Many to Many object to get another model property?

I'm coding a tooltip for a Django dashboard, so one of the scenarios says that when the user has not connected their Github account the repository link will be disabled. I already solved the problem but I didn't realized that it only works for the owner of the repo, so if I add somebody else as a collaborator, the link is going to work for them, because ofc, they are not the owners.

models.py

class Project(models.Model):
    owner = models.ForeignKey(
        TeamMember,
        related_name="github_repos",
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
    )

    members = models.ManyToManyField(
        TeamMember,
        related_name="new_projects",
        blank=True,
        through=ProjectMember,
    )

class TeamMember(models.Model):
    class Meta:
        unique_together = ("team", "user_id")

    django_user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        related_name="team_member",
        null=True,
        on_delete=models.SET_NULL,
    )
    team = models.ForeignKey(
        Team, related_name="members", on_delete=models.SET_NULL, null=True
    )
    github_username = models.CharField(max_length=100, blank=True)

So basically how I solved the problem was this way:

    def html_message(self):
        pattern = re.compile("Github Repository", re.IGNORECASE)

        if self.project.owner.has_connected_github:
            git_connection = self.project.owner.django_user.socialaccount_set.filter(
                provider="github"
            ).first()
            if git_connection:
                html_message = pattern.sub(
                    f"<a href='{self.project.html_url}'>Github Repository</a>", self.message
                )
            else:
                html_message = pattern.sub(
                    f"<a href='#' data-toggle='tooltip' title='Connect your Github account to access repository.'>Github Repository</a>", self.message
                ) 

That works but as I said before, only for the owner of the app, I need to know how to access to members, instead of owner, because as you can see is a Many to Many Field.

Any idea how can I access it? I saw similar questions but I don't fully understand them.

Upvotes: 1

Views: 93

Answers (2)

crazychukz
crazychukz

Reputation: 676

I would personally approach it this way

  1. Get all members in the project

    all_members = self.project.members.all()

this returns a QuerySet

  1. Loop through the all_members QuerySet and apply same logic you had for the owner

Like so

for member in all_members:
    if member.has_connected_github:
      .................

Upvotes: 0

valignatev
valignatev

Reputation: 6316

Since members is a m2m field, you can access TeamMember queryset through the project.members.all(). It's basically the same thing as TeamMember.objects.filter(project=self.project)

In order to show the correct message for a particular memeber, you should have access to this member in your html_message method. You probably have a user somewhere in your request or attached to the class. Here is an example:

# Pass the user to the method. Maybe you have it in the request.user somewhere near
def html_message(self, user): # or pass a request and then get request.user
    pattern = re.compile("Github Repository", re.IGNORECASE)

    member = self.project.members.filter(django_user=user)

    # It's not clear what your needs if a member does not exist,
    # so I'm taking a shourtcut
    if not member:
        return

    if member.has_connected_github:
        git_connection = user.socialaccount_set.filter(provider="github").first()
        if git_connection:
            html_message = pattern.sub(
                f"<a href='{self.project.html_url}'>Github Repository</a>", self.message
            )
        else:
            html_message = pattern.sub(
                f"<a href='#' data-toggle='tooltip' title='Connect your Github account to access repository.'>Github Repository</a>", self.message
            ) 

Upvotes: 1

Related Questions