Search code examples
pythonhtmldjangom2m

Using additional fields of a through m2m on template


My models.py:

class Profile(models.Model):
    name = models.CharField(max_length=32)
    gender = models.CharField(max_length=1, choices=(('m', 'male'),
        ('f', 'female')), default='m')
    addresses = models.ManyToManyField(City, 
        related_name='user_city', through='User_City')

class User_City(models.Model):
    user = models.ForeignKey(Profile)
    address = models.ForeignKey(City)
    phone = models.CharField(max_length=32)

    class Meta:
        unique_together = ("user", "address")

My view.py:

def user_profile(request, city):
    a=Profile.objects.filter(addresses=city)
    context_dict['lista'] = a
    ###first alternative:
    #b=User_City.objects.filter(user=request.user, address=city)
    #context_dict['lista_address'] = b
    ###second alternative:
    #for c in a:
        #b=User_City.objects.filter(user=c, address=city)
        #c.phone=b.phone
    #context_dict['lista_address'] = c

My template.html:

{% for user in lista %}
  {{ user.name }}
  {{ user.gender}}
  {{ user.phone }}
  #{{ user.addresses.phone }}
  #{{ user.addresses__phone }}
{% endfor %}

It read name and gender but not the phone... I tried many solutions but to no avail.

I can add the lista_address context_dict but then I don't know how to use in the template (I should find the right user in the for cycle).

I could add some attribute in the view but it don't work (attribute don't exist).

Thank for the help


Solution

  • addresses is a ManyToManyField, so how is {{ user.addresses.phone }} (or the likes thereof) supposed to know which of the addresses (City instances) is meant there to look up phone.

    Just loop directly over User_City objects, not Profiles:

    # view.py
    a = city.user_city_set.all()  # all through instances of city
    # a = User_City.objects.filter(address=city)
    
    # template.html
    {% for u_c in lista %}
      {{ u_c.user.name }}
      {{ u_c.user.gender}}
      {{ u_c.phone }}
    {% endfor %}
    

    One more point: 'user_city' is a very bad related_name! It is the related manager's name used to access the Profile instances of a City:

    city.user_city.all()  
    # Bad: because this is a QuerySet of Profiles
    # Better: related_name = 'users'