Hat
Hat

Reputation: 1731

django how to access m2m relationship in template

In my app, users can link profiles. In a sidebar that is visible on all pages of the site, I want to display the usernames of profiles a user is linked to. So far I have created an m2m field to link the profiles, and when a user logs in, I store this information in a session so it can be bundled with other session information and doesn't create another variable that has to be explicitly passed to each template. However, when accessing the list of linked profiles, I can only access the id's of the profiles, and not any other information about them.

model

class Profile(models.Model):
    username = models.CharField(max_length=25)
    link = models.ManyToManyField('self', null=True, blank=True, related_name='link_profiles')

view

def link_profiles(request, pid):
    #get both profiles
    my_p = Profile.objects.get(id=request.session['profile']['id'])
    their_p = Profile.objects.get(id=pid)

    #add profiles to eachothers links
    my_p.link.add(their_p)
    their_p.link.add(my_p)

    #save profiles
    my_p.save()
    their_p.save()

    #reset my session var to include the new link
    #this is that same bit of code that sets the session var when the user logs in
    request.session['profile'] = model_to_dict(my_p)

    return redirect('/profiles/' + pid)

template (using pyjade)

- for profile in session.profile.link
    div
        a(href="/profiles/{{ profile }}") profile {{ profile }}

This will output something like <a href='/profiles/5'>profile 5</a>, but using profile.id and profile.username just puts blank space in <a href='/profiles/'>profile</a>. Is it possible to access this information in this way without having to create another session variable (say request.session['links'])?

Upvotes: 0

Views: 164

Answers (1)

Gonzalo
Gonzalo

Reputation: 4269

model_to_dict will only give you a list of private keys (ids) and not all the data of the related objects.

That means you'll need to create that 'links' session variable by iterating through each of the related objects:

request.session['links'] = [model_to_dict(link) for link in my_p.links.all()]

If you want to optimize that, you could use sets, and only add the new profile:

data = model_to_dict(their_p)
if 'links' in request.session:
    request.session['links'].add(data)
else:
    request.session['links'] = set([data])

That should do it, but I think it may not be the best way. I'm not familiarized with PyJade, but I would pass the queryset returned by my_p.links.all() to the template in a context and iterate that instead.

Anyway, I hope that works for you.

Upvotes: 1

Related Questions