Python Forum

Full Version: how does a html form work exactly?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have been trying to teach myself Python Django.
Been following videos on YouTube.

I'm confused in understanding how this piece of code that has been added to create a form, works exactly.
Before I explain, I would like to point out that my model for the Song class has a Boolean field called is_favourite with the default set to False.

Here is the code for the form:

<form action="{% url 'music:favourite' album.id %}" method="post">
  {% csrf_token %}
  {% for song in album.song_set.all %}
      <input type="radio" id="song{{ forloop.counter }}" name="song" value="{{ song.id }}">
      <label for="song{{ forloop.counter }}">
          {{ song.song_title }}
          {% if song.is_favourite %}
              <img src="{% static 'music/images/star.jpg' %}" width="20" height="20">
          {% endif %}
      </label><br>
  {% endfor %}
  <input type="submit" value="Favourite">
</form>
I have attached an image of what the form looks like when I run the development server (it is boxed in red).
The purpose of the form is to allow users to "favourite" their songs.
When they have favourited their song(s), they click on the "Favourite" button which I believe submits all of the form data to the url 'music:favourite' which calls views.favourite function:

def favourite(request, album_id):
    album = get_object_or_404(Album, pk=album_id)
    selected_song = album.song_set.get(pk=int(request.POST['song']))
    if selected_song.is_favourite:
        selected_song.is_favourite = False
    else:
        selected_song.is_favourite = True
    selected_song.save()
    return render(request, 'music/detail.html', {'album':album})
I understand that the code in the form runs before the associated function in the view is called. Having said that, it is this line in the form code that I can't get my head around in understanding how it works:

{% if song.is_favourite %}
    <img src="{% static 'music/images/star.jpg' %}" width="20" height="20">
{% endif %}
I understand this is saying if the field "is_favourite" of the Song class is set to True, then add a little star image next to that song. But all songs are set to False when you try to run the form for the first time. So that line of code does not get executed i.e. a star image is not added to any of the songs. But let's say a user selects a song as a favourite and then clicks the submit button, does it only send that particular song the to the function in the view? If so, how does it know to only send that song, is this something to do with the mechanics of how "radio" button in html forms operates or am I missing something? Aside from this question, if the function then sets the field value of "is_favourite" of that particular song to True, then how does the "star" icon get added in the first place? We have already executed the lines of code in the form code and then we went to the view function which set the property to True so unless a call is made back to the code in the form to set the star icon, I don't quite understand.

Thank You in advance.
When you render the page and load the form for the first time is_favorite for all songs is False.
In the given example album has four songs. There is one radio control for each song. They have different ids and different value (the id of the song) but the same name ('song').
When you submit the form you post one key-value pair - {'song':song.id} where song.id is the respective id of the song (the value of the selected radio control).

Now your python function

    selected_song = album.song_set.get(pk=int(request.POST['song']))
    if selected_song.is_favourite:
        selected_song.is_favourite = False
    else:
        selected_song.is_favourite = True
    selected_song.save()
here it basically toggle the is_favourite property of the song - if it was True it will become False and vice-verse. This is important later on, because this is how you will in-favorite song that was previously favorite.

at the end of the python function you render the same page, however now the album that you pass has changed and one song is favorite. That is why the respective lines you identified correctly will execute and show a star next to the song. If you now submit the form with the same song selected, it will in-favorite it and next time page is rendered it will not display star next to it.

as a side note that
if selected_song.is_favourite:
    selected_song.is_favourite = False
else:
    selected_song.is_favourite = True
can be replaced with just
selected_song.is_favourite = not selected_song.is_favourite
thank you for the explanation.