How to display value of a field in a *linked* table, in a Django template?

耗尽温柔 提交于 2019-12-11 12:23:03

问题


I am creating a demo Django website where you browse Billy Joel's albums . You click on an album to view all songs.

(If it happens to be on: http://104.131.200.120/albums/all/--there's hardly any data at the moment. Only one song in Cold Spring Harbor, none in An Innocent Man)

I can't figure out how to display the song name in the album page. It can tell if there is a song, because Cold Spring Harbor prints out an empty "name/description" line, and An Innocent Man doesn't.

Here's the view

def album(request, album_id=1):
    album = Album.objects.get(id=album_id)
    album_songs = AlbumSong.objects.filter(id=album_id)
    print(str(album_songs))
    return  render_to_response("album.html",
                               {"album": album, "album_songs" : album_songs})

(the print results in [<AlbumSong: Cold Spring Harbor: 10: Got To Begin Again>] being written to the console, when Cold Spring Harbor is selected.)

The model (note that the Song and Album models are not linked by foreign key. There's an intermediate table, AlbumSong):

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

def get_upload_file_name(instance, filename):
    return  "uploaded_files/%s_%s" % (str(time()).replace(".", "_"), filename)

class Album(models.Model):
    title = models.CharField(max_length=70)
    pub_date = models.DateField('release date')
    is_official = models.BooleanField(default=False)
    is_concert = models.BooleanField(default=False)
    likes = models.IntegerField(default=0)
    thumbnail = models.FileField(upload_to=get_upload_file_name, blank=True, null=True)

    def __str__(self):
        return  self.title

class Song(models.Model):
    name = models.CharField(max_length=100)
    sub_name = models.CharField(max_length=200, null=True, blank=True)
    length_seconds = models.IntegerField()
    lyrics_url = models.TextField(default="", blank=True, null=True)

    def __str__(self):
        return  self.name

class AlbumSong(models.Model):
    song_id = models.ForeignKey(Song)
    album_id = models.ForeignKey(Album)
    sequence_num = models.IntegerField()

    class Meta:
        unique_together = ('album_id', 'sequence_num',)
        unique_together = ('album_id', 'song_id',)

    def __str__(self):
        return  str(self.album_id) + ": " + str(self.sequence_num) + ": " + str(self.song_id)

class FavoriteSongs(models.Model):
    user_id = models.ForeignKey(User)
    song_id = models.ForeignKey(Song)
    sequence_num = models.IntegerField()

    class Meta:
        unique_together = ('user_id', 'song_id',)
        unique_together = ('user_id', 'sequence_num',)

    def __str__(self):
        return  "user=" + str(self.user_id) + ", song=" + str(self.song_id) + ", number=" + str(self.sequence_num)

class FavoriteAlbums(models.Model):
    user_id = models.ForeignKey(User)
    album_id = models.ForeignKey(Album)
    sequence_num = models.IntegerField()

    class Meta:
        unique_together = ('user_id', 'album_id',)
        unique_together = ('user_id', 'sequence_num',)

    def __str__(self):
        return  "user=" + str(self.user_id) + ", album=" + str(self.album_id) + ", number=" + str(self.sequence_num)

and template:

{% extends "base.html" %}

{% block title %}Album detail{% endblock %}

<!-- <div id="sidebar"> -->
{% block sidebar %}
  <UL>
     <LI><a href="/albums/all">Albums</A></LI>
  </UL>
{% endblock %}
<!-- </div> -->


{% block content %}

<H1>{{ album.title }}</H1>

<P>{{ album.body }}</P>

{% if album.thumbnail %}
  <P><img src="/static/{{ album.thumbnail }}" width="200"/></P>
{% endif %}

<P><UL>
  <LI>Released: {{ album.pub_date }}</LI>
  <LI>Official: {{ album.is_official }}</LI>
  <LI>Concert: &nbsp;{{ album.is_concert }}</LI>
</UL></P>
  <H2>Songs</H2>

{% for  album_song in album_songs %}  <!-- No colon after "album_songs" -->
  <div>
  <P><UL>
     <LI>Name: <a href="/songs/get/{{ song.id }}">{{ album_song.song.name }}</a><UL>
        <LI>Description: {{ album_song.song.sub_name }}</LI>
     </UL></LI>
  </UL></P>
  </div>
{% endfor %}
<P><a href="/albums/like/{{ album.id }}">Like this album</A> -- {{ album.likes }} people liked this album.</P>

{% endblock %}

How do I display the song name in the template? What should album_song.song.name be changed to?

Thank you.


回答1:


The problem is your field names. For some reason, you've called your foreign keys from AlbumSong "song_id" and "album_id". So you should use the same names in the template: {{ album_song.song_id.name }}.

However, it doesn't make sense to use this name. The Django field does not represent an ID, it represents the actual Song object. Django already creates an underlying database field with an "_id" suffix, so in this case it's created one called "song_id_id", which is silly. Rename your fields "song" and "album", and keep your template the way it is.



来源:https://stackoverflow.com/questions/25232741/how-to-display-value-of-a-field-in-a-linked-table-in-a-django-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!