mp3909
mp3909

Reputation: 19

Python Django Form submit button not working as desired

I have been trying to learn Django. I am stuck on this form part. A form has been created that allows the user to create an Album object where they can fill in the Artist, Album Name, Genre and upload an Album Logo. When I fill in the fields and then click submit, it should then redirect me to the details page for that particular Album that just got created. But nothing appears to happen when clicking the submit button and the object does not get created.

Here is the models.py code that contains an Album class with 4 fields; artist, album_name, genre and album_logo.

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

# Create your models here.
class Album(models.Model):
    artist = models.CharField(max_length=250)
    album_name = models.CharField(max_length=500)
    genre = models.CharField(max_length=100)
    album_logo = models.ImageField()

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

    def __str__(self):
        return self.album_name + " - " + self.artist

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

    def __str__(self):
        return self.song_title

Here is the album_form.html code which contains the actual form. I have not used crispy_forms as I am not familiar with Bootstrap though I know CSS.

{% extends 'music/base.html' %}

{% block title %}Add a New Album{% endblock %}
{% block body %}
    <form class="formContainer" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {% for field in form %}
            {% if field.label != 'Album logo' %}
                <label for="field{{ forloop.counter }}">{{ field.label }}</label>
                <input type="text" id="field{{ forloop.counter }}" name="" value="">
            {% else %}
                <label for="field{{ forloop.counter }}">{{ field.label }}</label>
                <input type="file" id="field{{ forloop.counter }}" name="" value="" accept="image/*">
            {% endif %}
            <br>
        {% endfor %}
        <input type="submit" id="submitBtn" name="" value="Add">
    </form>
{% endblock %}

This is views.py code where I have made use of class based views and not function based views.

from django.views import generic from .models import Album, Song

# Create your views here.
class IndexView(generic.ListView):
    template_name = 'music/index.html'
    queryset = Album.objects.all()
    context_object_name = 'all_albums'


class DetailView(generic.DetailView):
    model = Album
    template_name = 'music/detail.html'


class AlbumCreate(generic.CreateView):
    model = Album
    fields = ['artist', 'album_name', 'genre', 'album_logo']

    def form_valid(self, form):
        return super().form_valid(form)

and finally this is my urls.py code:

from django.urls import path, include
from . import views

app_name='music'

urlpatterns = [
    #/music/
    path('', views.IndexView.as_view(), name='index'),

    #/music/5/
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),

    #/music/album/add/
    path('album/add/', views.AlbumCreate.as_view(), name='album-add')
]

After clicking the submit button in the form, it should take me to the "detail" url for the primary key of the Album that got created. Am I missing something here?

Upvotes: 0

Views: 824

Answers (2)

Sherzod Sadriddinov
Sherzod Sadriddinov

Reputation: 116

Seems you forgot to put action to your <form> tag

Try this

<form class="formContainer" action='{% url 'music:album-add'%}' method="post" enctype="multipart/form-data">

Edit: Also add success url using get_success_url function in your AlbumCreate view to redirect user to album detail page, like was mentioned in above answer

from django.urls import reverse_lazy
...
class AlbumCreate(generic.CreateView):
    ...
    def get_success_url(self, **kwargs):
        return reverse_lazy('music:detail', args = (self.object.id,))

Upvotes: 0

Harben
Harben

Reputation: 1856

In your views.py you need to override the get_success_url function in your CreateView and pass the id as an argument while redirecting.

class AlbumCreate(generic.CreateView):
    model = Album
    fields = ['artist', 'album_name', 'genre', 'album_logo']

    def form_valid(self, form):
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('music:detail', args=(self.object.id,))

Upvotes: 1

Related Questions