Sunday 31 March 2019

django 25 generic views field overwrite, pass parameter to templates

3 songs in album (the great expense)

click add song, song album field is auto filled (overwritten with current album)

new song created in album

edit last song created, all fields are auto filled , check favorite

last song is updated to favorite

#music/urls
    ...
    #music/song/add/
    path('song/<album_pk>/add/', views.SongCreate.as_view(), name='song-add'),

    #music/song/id/
    path('song/<album_pk>/<pk>/', views.SongUpdate.as_view(), name='song-update'),

    #music/song/id/delete/
    path('song/<album_pk>/<pk>/delete/', views.SongDelete.as_view(), name='song-delete'),

---------------------------------
#music/views
...
#protected route, require authentication
class SongCreate(LoginRequiredMixin, CreateView):
    model = Song
    fields = ['file_type', 'song_title', 'is_favorite']

    #overwrite field['album']
    def form_valid(self, form):
        form.instance.album = Album.objects.get(pk=self.kwargs['album_pk'])
        return super().form_valid(form)

    #pass variable song_album to song_form template
    def get_context_data(self, **kwargs):
        context = super(SongCreate, self).get_context_data(**kwargs)

        song_album = Album.objects.get(pk=self.kwargs['album_pk']).album_title

        context.update({'song_album':song_album})
        return context

class SongUpdate(LoginRequiredMixin, UpdateView):
    model = Song
    fields = ['file_type', 'song_title', 'is_favorite']

    # overwrite field['album']
    def form_valid(self, form):
        form.instance.album = Album.objects.get(pk=self.kwargs['album_pk'])
        return super().form_valid(form)

    # pass variable song_album to song_form template
    def get_context_data(self, **kwargs):
        context = super(SongUpdate, self).get_context_data(**kwargs)

        song_album = Album.objects.get(pk=self.kwargs['album_pk']).album_title

        context.update({'song_album': song_album})
        return context

class SongDelete(LoginRequiredMixin, DeleteView):
    model = Song
    #redirect to detail page after delete
    def get_success_url(self):
        return  reverse_lazy('music:detail',kwargs={'pk': self.kwargs['album_pk']})

------------------------------------
#music/templates/detail

{% extends 'music/base.html' %}
{% block title %}Songs{% endblock %}

{% block body %}

    <div class="row">
        <div class="col">
            <img style="height: 150px; margin-bottom: 20px;" src="{{album.album_logo.url}}"><br>
            <h4>Title: {{album.album_title}}</h4>
            <h4>Artist: {{album.artist}}</h4>
            <h4>Genre: {{album.genre}}</h4>
        </div>

        <div class="col">
            <div>
                <a href="{% url 'music:song-add' album.id%}" class="btn btn-success btn-sm" role="button">
                    <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Song
                </a>
            </div>

            <ul class="list-group list-group-flush">
                {% for song in album.song_set.all %}
                    <li class="list-group-item d-flex justify-content-between align-items-center">
                        <div>
                            {{ song.song_title }}

                            {% if song.is_favorite %}
                                <span class="glyphicon glyphicon-heart" aria-hidden="true"></span>
                            {% endif %}
                        </div>

                        <div>
                            <!-- Edit -->
                            <a class="btn btn-default btn-sm" href="{% url 'music:song-update' album.id song.id %}">
                                <span class="glyphicon glyphicon-pencil"></span>
                            </a>

                             <!-- Delete -->
                            <a class="btn btn-default btn-sm" href="{% url 'music:song-delete' album.id song.id %}">
                                <span class="glyphicon glyphicon-trash"></span>
                            </a>
                        </div>
                    </li>
                {% endfor %}
            </ul>
        </div>
    </div>

{% endblock %}

------------------------------------------------------
#music/templates/song_form

{% extends 'music/base.html' %}
{% block title %}Song{% endblock %}
{% load crispy_forms_tags %}

{% block body %}
    <div class="container-fluid">

        <div class="row">

            <div class="col-sm-12 col-md-7">

                <form  action="" method="post" enctype="multipart/form-data">
                    {% csrf_token %}
                    <fieldset class="form-group">
                        <legend class="border-bottom mb-4">Create/Update Song</legend>
                    </fieldset>
                    <div class="form-group">
                        <label for="disabledTextInput">Album</label>
                        <input type="text" id="disabledTextInput" class="form-control" value="{{song_album}}" disabled="disabled">
                        <br>
                        {{ form|crispy }}

                        <button class="btn btn-success btn-sm" type="submit">Submit</button>
                    </div>
                </form>

            </div>
        </div>
    </div>

{% endblock %}

---------------------------------------
#music/models

from django.db import models
from django.urls import reverse

class Album(models.Model):
    artist = models.CharField(max_length=50)
    album_title = models.CharField(max_length=50)
    genre = models.CharField(max_length=50)
    album_logo = models.FileField()

    #form submitted without action redirect to detail
    def get_absolute_url(self):
        return reverse('music:detail', kwargs={'pk': self.pk})

    #query album.objects.get(pk=1)
    def __str__(self):
        return self.album_title + ' - ' + self.artist

class Song(models.Model):
    album = models.ForeignKey(Album, on_delete=models.CASCADE)
    file_type = models.CharField(max_length=50)
    song_title = models.CharField(max_length=50)
    is_favorite = models.BooleanField(default=False)

    def __str__(self):
        return self.song_title

        # form submitted without action redirect to detail
    def get_absolute_url(self):
        return reverse('music:detail', kwargs={'pk': self.album.id})

reference:
https://stackoverflow.com/questions/26407863/passing-parameters-to-django-createview
https://stackoverflow.com/questions/18232851/django-passing-variables-to-templates-from-class-based-views

No comments:

Post a Comment