Retrieving and Displaying a ManyToMany field in Django from a OnetoOne Class

75 views Asked by At

I am trying to display a list of trees a user can 'heart' in Django and am having no luck.

models.py

from django.db import models
from django.contrib.auth.models import User


class Tree(models.Model):

    treeId = models.IntegerField(primary_key=True)
    neighbourhood = models.CharField(max_length=128,blank=True)
    commonName = models.CharField(max_length=128, blank=True)
    diameter = models.FloatField(blank=True)
    streetNumber = models.PositiveSmallIntegerField(blank=True)
    street = models.CharField(max_length=128, blank=True)



class UserProfile(models.Model):
    # This line is required. Links UserProfile to a User model instance.
    user = models.OneToOneField(User)


    # Tree field is used to store user's favourite trees
    tree = models.ManyToManyField(Tree, blank=True)

views.py

@login_required
def favourites(request):

    current_user = UserProfile.objects.get(id=request.user.id)
    tree_list = current_user.tree.all()
    context_dict = {'trees' : tree_list}
    return render(request, 'hug/favourites.html', context_dict)

favourites.html

            {% for tree in trees %}
            <p>tree id   -   {{ tree.treeId }}</p>
            <p> {{ tree.commonName|title }}</p>
            {% endfor %}

I have tried print statements and it seems to not like this line of code: tree_list = current_user.tree.all() (as it does not print anything) and when I run the code on the server I get:

UserProfile matching query does not exist.

Any advice would be much appreciated.

Thanks,

A

1

There are 1 answers

1
Daniel Roseman On BEST ANSWER

There are a few problems with your code.

Firstly, the Tree model defines the primary key as an IntegerField, not an AutoField. That means that it won't allocate ids automatically; so you will probably get an IntegrityError when you try and add new trees. Unless there is a really good reason for this, you should omit this field and let Django define its own automatic id.

Secondly, your code to get the UserProfile is wrong. You are trying to get the UserProfile whose ID is the same as the current user's ID. That assumes that the IDs in User and UserProfile are the same; and there is no reason to assume that. This is almost certainly why you get that "does not exist" error: you are looking up the wrong ID.

The correct way to get the UserProfile from the User is by doing:

user_profile = request.user.userprofile

However, I would question why you need the UserProfile model at all. The only thing it contains is the ManyToManyField; and since it makes no difference what side of the relationship you define those on, why not put it into Tree and make the relationship directly with User? That avoids the whole lookup and simplifies the problem immensely. Then you would be able to do:

tree_list = request.user.tree.all()