andrewlis
andrewlis

Reputation: 41

Django: how to update model attribute through a view?

I have albums and songs. When at specific album page I want to add a song by clicking "Add Song" button and return to that album's page: Album's page The from opens fine and lets me input song title. But when I click "Submit" it breaks with this exception: Exception Here is a portion of template code where form is called:

{% block body %}

<div class="container-fluid" style="position:relative; padding-left: 100px; padding-top: 50px;">
    <img src="{{ album.album_logo.url }}" class="img-responsive" height="200" width="200">

    <h1>{{ album.album_title }}</h1>
    <h3>{{ album.artist }}</h3>

    {% for song in album.song_set.all %}
        {{ song.song_title }}
        {% if song.is_favorite %}
            <img src="http://vignette1.wikia.nocookie.net/defendersquest/images/1/17/Yellow_star_small.png/revision/latest?cb=20120430053933"
            height="10" width="10"/>
        {% endif %}
        <br>
    {% endfor %}

    <a href="{% url 'music:song-add' album.pk %}">
        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp; Add Song
    </a>
</div>

{% endblock %}

Here is urls.py:

    urlpatterns = [

    # /music/
    url(r'^$', views.IndexView.as_view(), name='index'),  # "$" sign means nothing more was requested from user

    # /music/<album_id>/ - here album_id is an ID of specific Album for example
    url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'), # this will look for numbers 0-9 in user request
    #and map it to variable named 'album_id'. Plus sign emplies to look for one or more numbers
    #^-sign implies begingin of reg. expression and $-implies the end of it.

    # /music/album/add/
    url(r'album/add/$', views.AlbumCreate.as_view(), name='album-add'),

    # /music/album/add/
    url(r'song/add/(?P<album_pk>[0-9]+)/$', views.SongCreate.as_view(), name='song-add'),

    # /music/album/album_id/
    url(r'album/(?P<pk>[0-9]+)/$', views.AlbumUpdate.as_view(), name='album-update'),

    # /music/album/album_id/delete/
    url(r'album/(?P<pk>[0-9]+)/delete/$', views.AlbumDelete.as_view(), name='album-delete')
]

Here is views.py portion:

class SongCreate(CreateView):
    model = Song
    fields = ['song_title']

    def form_valid(self, form):
        form.instance.album.pk = self.request.GET.get('album_pk')
        return super(SongCreate, self).form_valid(form)

and here is models.py:

class Album(models.Model):
    # attributes/columns:
    artist = models.CharField(max_length=250) #CharField is the info on type of info that var holds
    album_title = models.CharField(max_length=500)
    genre = models.CharField(max_length=100)
    album_logo = models.FileField()

    def get_absolute_url(self):
        return reverse('music:detail', kwargs={'pk': self.pk})
    def __str__(self): #string representation of Album objects
        return self.album_title + ' - ' + self.artist

class Song(models.Model):
    #attributes/columns:
    album = models.ForeignKey(Album, on_delete=models.CASCADE)  #linking songs to Albums!!!
    file_type = models.CharField(max_length=10)
    song_title = models.CharField(max_length=250)
    is_favorite = models.BooleanField(default=False)

    def get_absolute_url(self):
        return reverse('music:detail', kwargs={'pk': self.album.pk})

    def __str__(self):
        return self.song_title

Upvotes: 1

Views: 558

Answers (1)

Moses Koledoye
Moses Koledoye

Reputation: 78554

You're not setting the related ForeignKey object correctly. You can access the pk of the related field using the hidden _id field of the related object in the model instance:

form.instance.album_id = self.request.GET.get('album_pk')

Upvotes: 1

Related Questions