I have tried passing Album objects and song objects to my DetailView trying to get the DetailView working with both Album models and Song model. But anytime I try deleting a song my code cant seem to get the Song.objects.all(). I get a cannot find a song object in query or something like that
here are my url patterns:
urlpatterns =
[
/music/
url(r'^$', views.IndexView.as_view(), name='index'),
# /music/album_id/
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^register/$', views.UserFormView.as_view(), name='register'),
url(r'album/add/$', views.AlbumCreate.as_view(), name='album-add'),
#/music/album/2/
url(r'album/(?P<pk>[0-9]+)/$', views.AlbumUpdate.as_view(), name='album-update'),
#/music/album/add/delete/
url(r'^album/(?P<pk>[0-9]+)/delete/$', views.AlbumDelete.as_view(), name='album-delete'),
#/music/album/album_id/add-song/
url(r'^album/(?P<pk>[0-9]+)/add-song/$', views.SongView.as_view(), name='song-add'),
# /music/album_id/song/delete/
url(r'^album/song/delete/(?P<song_id>[0-9]+)/$', views.SongDelete.as_view(), name='song-delete'),
views.py:
class IndexView(generic.ListView):
template_name = 'music/index.html'
context_object_name = 'all_albums'
def get_queryset(self):
return Album.objects.all()
class DetailView(generic.DetailView):
template_name = 'music/detail.html'
model = [Album, Song]
# context_object_name = 'all_songs'
def get_object(self, queryset=Song.objects.all()):
return queryset
def get_queryset(self):
return Album.objects.all()
class AlbumCreate(CreateView):
model = Album
fields = ['artist','album_title', 'genre', 'album_logo']
class AlbumUpdate(UpdateView):
model = Album
fields = ['artist','album_title', 'genre', 'album_logo']
class AlbumDelete(DeleteView):
model = Album
success_url = reverse_lazy('music:index')
class UserFormView(generic.View):
form_class = UserForm
template_name='music/registration_form.html'
#displays a blank form
def get(self, request):
form = self.form_class(request.GET)
return render(request, self.template_name, {'form': form})
#process form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user=form.save(commit=False)
#cleand (Normalized) data
username= form.cleaned_data['username']
password=form.cleaned_data['password']
user.set_password(password)
user.save()
#Returns user object if cresentials are correct
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('music:index')
return render(request, self.template_name, {'form': form})
class SongView(CreateView):
# template_name = 'music/song_form.html'
model = Song
fields= ['title', 'album', 'audio_file', 'favorite']
class SongDelete(DeleteView):
model = Song
success_url = reverse_lazy('music:detail')
models.py:
from django.db import models
from django.core.urlresolvers import reverse
class Album(models.Model):
artist=models.CharField(max_length=250)
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):
return self.album_title + '_' + self.artist
class Song(models.Model):
title=models.CharField(max_length=250)
album=models.ForeignKey(Album, on_delete=models.CASCADE)
audio_file= models.FileField()
favorite=models.BooleanField(default=False)
def get_absolute_url(self):
return reverse('music:detail' , kwargs={'pk': self.pk})
def __str__(self):
return self.title
please need help, been o this for a while now **wheww
If you need all songs in your DetailView you should pass them in the context; they are completely separate from the queryset of Albums you need to use to find the current object.
class DetailView(generic.DetailView):
template_name = 'music/detail.html'
model = Album
def get_context_data(self, *args, **kwargs):
context = super(DetailView, self).get_context_data(*args, **kwargs)
context['all_songs'] = Song.objects.all()
return context
(In future, please also post only relevant code and ensure that your indentation is correct.)
Related
I hope you are well.
I'm trying to create comment for user with one form field (content). I'd like to have the user field automatically filled in user value.
I. I started with this model but I got an error (1048, “Column 'user_id' cannot be null”):
models.py
class Comment(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name="comments")
user = models.ForeignKey(User,on_delete=models.CASCADE)
content = models.TextField(max_length=160)
publishing_date = models.DateField(auto_now_add=True)
def __str__(self):
return self.post.title
views.py
class PostDetail(generic.DetailView,FormMixin):
model = Post
context_object_name = 'post'
template_name = 'post_detail.html'
form_class = CreateCommentForm
def get_context_data(self, **kwargs):
context = super(PostDetail, self).get_context_data(**kwargs)
context['form'] = self.get_form()
return context
def form_valid(self, form):
if form.is_valid():
form.instance.post = self.object
form.save()
return super(PostDetail, self).form_valid(form)
else:
return super(PostDetail, self).form_invalid(form)
def post(self,*args,**kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_valid(form)
def get_success_url(self):
return reverse('post_detail',kwargs={"slug":self.object.slug})
forms.py
class CreateCommentForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
super(CreateCommentForm, self).__init__(*args,**kwargs)
self.helper = FormHelper()
self.helper.form_method="post"
self.helper.layout = Layout(
Field("content",css_class="form-control",style="margin-bottom:10px",rows="1"),
)
self.helper.add_input(Submit('submit','Comment',css_class="btn btn-sm",style="background-color: #0d6ec5;border-color: #0d6ec5;"))
class Meta:
model = Comment
fields = [
'content'
]
II. It worked from my admin panel but not from my website (I got this error: (1048, “Column 'user_id' cannot be null”)).
So I've decided to change my models with:
class Comment(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name="comments")
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
content = models.TextField(max_length=160)
publishing_date = models.DateField(auto_now_add=True)
def __str__(self):
return self.post.title
The thing is if a user post a comment, content is ok but there is no user related to the comment. Anyone has an idea?
You need to specify the .user attribute, probably to the logged in user:
from django.contrib.auth.mixins import LoginRequiredMixin
class PostDetail(LoginRequiredMixin, FormMixin, generic.DetailView):
model = Post
context_object_name = 'post'
template_name = 'post_detail.html'
form_class = CreateCommentForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = self.get_form()
return context
def form_valid(self, form):
form.instance.post = self.object
form.instance.user = self.request.user
return super().form_valid(form)
def post(self,*args,**kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_valid(form)
def get_success_url(self):
return reverse('post_detail',kwargs={"slug":self.object.slug})
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin mixin [Django-doc].
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Context:
In the Blog part of page any registered User can post, but all posts that are from non superuser accounts have to be approved by an admin on the Admin page where I registered the model as well.
This functions as intended.
My question:
How can I make it so that if a Blog Post gets updated by a superuser(doesn't matter what kind of a change for example: when admin opens one single post and adds in a further text in the body of the post, or deletes some part of a text because it seems malicious or fake), that it is automatically approved(The field approved gets then set to TRUE)?
I already thought of adding a further field in the model called changed_by and have it initially null.
Code:
blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class BlogPost(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
approved = models.BooleanField(default=False)
changed_by = models.ForeignKey(User, default=None) # I am planning to use this but how?
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blogPost-detail', kwargs={'pk': self.pk})
blog/admin.py
from django.contrib import admin
from .models import BlogPost
def approve_multiple_posts(modeladmin, request, queryset):
for blogPost in queryset:
if blogPost.approved:
blogPost.approved = False
else:
blogPost.approved = True
blogPost.save()
approve_multiple_posts.short_description = 'Change approval status'
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'date_posted', 'approved']
actions = [approve_multiple_posts, ]
admin.site.register(BlogPost, PostAdmin)
blog/views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from .models import BlogPost
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
def blog(request):
context = {
'blogPosts': BlogPost.objects.all()
}
return render(request, 'blog/blog.html', context)
class PostListView(ListView):
model = BlogPost
template_name = 'blog/blog.html'
context_object_name = 'blogPosts'
ordering = ['-date_posted']
paginate_by = 5
def get_queryset(self):
return BlogPost.objects.filter(approved=True).order_by('-date_posted')
class UserPostListView(ListView):
model = BlogPost
template_name = 'blog/user_blogPosts.html'
context_object_name = 'blogPosts'
paginate_by = 5
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return BlogPost.objects.filter(author=user, approved=True).order_by('-date_posted')
class PostDetailView(DetailView):
model = BlogPost
class PostCreateView(LoginRequiredMixin, CreateView):
model = BlogPost
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
if self.request.user.is_superuser:
form.instance.approved = True
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = BlogPost
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
blog_post = self.get_object()
if self.request.user == blog_post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = BlogPost
success_url = '/blog'
def test_func(self):
blog_post = self.get_object()
if self.request.user == blog_post.author:
return True
return False
I would appreciate any help/suggestions you have! Thanks
In your PostAdmin class, you can override a method called save_model (Django docs). Try something like this:
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'date_posted', 'approved']
actions = [approve_multiple_posts, ]
def save_model(self, request, obj, form, change):
important_fields = ['title', 'content'] # modify save if these fields changed
if any(x in important_fields for x in form.changed_data):
obj.approved = request.user.is_superuser
super().save_model(request, obj, form, change)
This will make approved True only if the user is a superuser, otherwise it will be set to False.
im only student so please bear with me. I already posted another topic about this but in function view. now i want to how do i convert this try exception to a class view and also add that comment form.
here's my views.py def
def BookDetail(request, id):
most_recent = Book.objects.order_by('-timestamp')[:3]
book= get_object_or_404(Book, id=id)
form = CommentForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.instance.user = request.user
form.instance.post = book
form.save()
return redirect(reverse("book-detail", kwargs={
'id': book.pk
}))
if request.user.is_anonymous:
user_membership = None
else:
try:
user_membership = Customer.objects.get(user=request.user)
except Customer.DoesNotExist:
user_membership = None
context = {
'user_membership': user_membership,
'form': form,
'book': book,
'most_recent': most_recent,
}
return render(request, 'catalog/book_detail.html', context)
here is my new class view
class BookDetailView(NeverCacheMixin, generic.DetailView):
model = Book
UPDATE POST
here's my models.py..
class Book(models.Model):
slug = models.SlugField(unique=True, help_text="Enter BIC Code", null=True)
title = models.CharField(max_length=200) #more fields after this
timestamp = models.DateTimeField(default=timezone.now)
activeReference = models.ManyToManyField(Membership)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('book-detail', kwargs={'slug': self.slug})
#property
def get_comments(self):
return self.comments.all().order_by('-timestamp')
#property
def pages(self):
return self.page_set.all()
class Page(models.Model):
slug = models.SlugField(max_length=50)
book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)
preview = models.FileField(upload_to='book_content', validators=[pdf_file_extension], help_text="PDF File Only")
def __str__(self):
return self.slug
def get_absolute_url(self):
return reverse('page-detail',
kwargs={
'book_slug': self.book.slug,
'page_slug': self.slug
})
here's my URL pattern
urlpatterns = [
path('', views.index, name='index'),
path('books/', views.BookListView.as_view(), name='book-list'),
path('book-detail/<slug>', views.BookDetailView.as_view(), name='book-detail'),
path('book-detail/<book_slug>/<page_slug>', views.PageDetailView.as_view(), name='page-detail'),
path('search/', views.Search, name='search'),
]
and my book_detail.html
{% for content in book.pages %}
Read
{% endfor %}
{% else %}
CBV are good when you need inheritance or need to deal with different HTTP methods to have the same route. If that is not the case, a FBV is a better choice. That being said, for what you are trying to do, you should just a FormView that will handle everything about a post and forms.
Something like:
class BookViewSet(FormView):
form = CommentForm
template_name = 'catalog/book_detail.html'
def form_valid(self, form):
self.send_mail(form.cleaned_data)
return super(BookViewSet, self).form_valid(form)
If you are handling forms, you should be using CreateView or FormView not DetailView. Here is an implementation example, as you can see is a little complex for someone new to Django:
from django.views.generic import CreateView
class BookDetailView(NeverCacheMixin, CreateView):
form_class = CommentForm
template_name = 'catalog/book_detail.html'
def dispatch(self, request, *args, **kwargs):
book_slug = self.kwargs.get('slug') # url variables are stored in self.kwargs
self.book = get_object_or_404(Book, slug=book_slug) # attach book to your view
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
# context data passed to template
kwargs['book'] = self.book
kwargs['most_recent'] = Book.objects.order_by('-timestamp')[:3]
if request.user.is_anonymous:
user_membership = None
else:
try:
user_membership = Customer.objects.get(user=self.request.user)
except Customer.DoesNotExist:
user_membership = None
kwargs['user_membership'] = user_membership
return super().get_context_data(**kwargs)
def form_valid(self, form):
instance = form.save(commit=False)
instance.user = self.request.user
instance.post = self.book
instance.save()
return redirect(self.book.get_absolute_url())
I am very new to Django so don't judge me :). I am making a blog project and everything works well except one thing. When creating a post, the user can choose any other author that has previously logged in. Is there any way to set the author namespace as the currently logged in user? Here is my code:
Models.py
from django.db import models
from django.utils import timezone
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User
def validate_even(value):
if value == 'auth.User':
raise ValidationError(
_('%(value)s is not an even number'),
params={'value': value},
)
class Post(models.Model):
author = models.ForeignKey('auth.User')
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True,null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse('post_detail', args=(), kwargs={'pk':self.pk})
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('blog.post',related_name='comments')
author = models.ForeignKey('auth.User')
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def get_absolute_url(self):
return reverse('post_list')
def __str__(self):
return self.text
class UserProfileInfo(models.Model):
user = models.OneToOneField(User)
def __str__(self):
return self.user.username
My forms.py
from django import forms
from blog.models import Comment,Post
from django.contrib.auth.models import User
from blog.models import UserProfileInfo
class PostForm(forms.ModelForm):
class Meta():
model = Post
fields = ['author','title','text']
widgets = {
'title':forms.TextInput(attrs={'class':'textinputclass','autocomplete':'true'}),
'text':forms.Textarea(attrs={'class':'editable medium-editor-textarea postcontent'})
}
class CommentForm(forms.ModelForm):
class Meta():
model = Comment
fields = ['text']
widgets = {
'text':forms.Textarea(attrs={'class':'editable medium-editor-textarea'})
}
def __init__(self, *args, **kwargs):
from django.forms.widgets import HiddenInput
hide_condition = kwargs.pop('hide_condition',None)
super(CommentForm, self).__init__(*args, **kwargs)
if hide_condition:
self.fields['author'].widget = HiddenInput()
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(attrs={'autocomplete':'false'}))
username = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'false'}))
class Meta():
model = User
fields = ('username', 'email', 'password')
widgets = {
'password':forms.TextInput(attrs={'autocomplete':'false'}),
'username':forms.TextInput(attrs={'autocomplete':'false'}),
}
My views.py
from django.shortcuts import render, get_object_or_404,redirect
from django.utils import timezone
from django.views.generic import (TemplateView,ListView,DetailView,CreateView,UpdateView,DeleteView)
from blog.models import Comment,Post
from blog.forms import PostForm,CommentForm
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
from django.contrib import auth
from blog.forms import UserForm
from django.contrib.auth import views
from django.contrib.auth.models import User
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
registered = True
if registered:
views.login(request)
return redirect("/")
else:
print(user_form.errors)
else:
user_form = UserForm()
return render(request, 'registration/registration.html',{'user_form':user_form,registered:'registered'})
class AboutView(TemplateView):
template_name = 'about.html'
class PostListView(ListView):
model = Post
template_name = 'post_list.html'
def get_queryset(self):
return Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
class PostDetailView(DetailView):
model = Post
class CreatePostView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'blog/post_detail.html'
form_class = PostForm
model = Post
def get_queryset(self):
return Post.objects.filter(author=self.request.user)
form_class = PostForm
form_class.author = self.request.user
class PostUpdateView(LoginRequiredMixin,UpdateView):
login_url = '/login/'
redirect_field_name = 'blog/post_detail.html'
model = Post
form_class = PostForm
class PostDeleteView(LoginRequiredMixin,DeleteView):
model = Post
success_url = reverse_lazy('post_list')
class DraftListView(LoginRequiredMixin,ListView):
login_url = '/login/'
redirect_field_name = 'blog/post_list.html'
model = Post
def get_queryset(self):
return Post.objects.filter(published_date__isnull=True).order_by('created_date')
#login_required
def add_comment_to_post(request,pk):
post = get_object_or_404(Post,pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
# comment.save()
instance = form.save(commit=False)
instance.author = request.user
instance.save()
return redirect('post_detail',pk=post.pk)
else:
form = CommentForm
return render(request,'blog/comment_form.html',context={'form':form})
#login_required
def comment_approve(request,pk):
comment = get_object_or_404(Comment,pk=pk)
comment.approve()
return redirect('post_detail',pk=comment.post.pk)
#login_required
def comment_remove(request, pk):
comment = get_object_or_404(Comment, pk=pk)
post_pk = comment.post.pk
comment.delete()
return redirect('post_detail', pk=post_pk)
#login_required
def post_publish(request,pk):
post = get_object_or_404(Post,pk=pk)
post.publish()
return redirect('post_detail',pk=pk)
I have tried absolutely everything and nothing worked. Can anyone please help me?
In your PostForm, remove author from the fields, so it cannot be edited by the user:
fields = ['title', 'text']
Then in your CreatePostView, remove the def get_queryset() method as it doesn't do anything here. You should instead override the form_valid method, that's where you get a chance to update the model that was created by the form.
def form_valid(self, form):
self.object = form.save(commit=False) # the form's save method returns the instance
self.object.author = self.request.user # here you assign the author
self.object.save()
return HttpResponseRedirect(self.get_success_url())
Alternatively, to keep as close as possible to the CreateView parent class:
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form) # this will call `CreateView`'s `form_valid()` method, which saves the form.
I am using django 1.11.6 and python 3.6.2
I'm new to django and there is no one to help me where i live so you guys are all my hope
in my django application in the add song section i faced an error
error message =
IntegrityError at /music/album/5/AddSong/ NOT NULL constraint failed:
music_song.album_id
here is my views file:
from django.views import generic
from django.views.generic import View
from .forms import UserForm
from django.views.generic.edit import CreateView,UpdateView,DeleteView
from django.shortcuts import render,redirect
from django.contrib.auth import authenticate, login
from .models import Album, Song
from django.core.urlresolvers import reverse_lazy
class IndexView(generic.ListView):
template_name = 'music/index.html'
context_object_name = 'all_albums'
def get_queryset(self):
return Album.objects.all()
class DetailView(generic.DetailView):
model = Album
template_name = 'music/detail.html'
context_object_name = 'album'
class AlbumCreate(CreateView):
model = Album
fields = ['artist', 'album_title', 'genre', 'album_logo']
class SongCreate(CreateView):
model = Song
fields = ['song_title', 'file_type']
class AlbumUpdate(UpdateView):
model = Album
fields = ['artist', 'album_title', 'genre', 'album_logo']
class AlbumDelete(DeleteView):
model = Album
success_url = reverse_lazy('music:index')
class UserFormView(View):
form_class = UserForm
template_name = 'music/registration_form.html'
#display a blank form
def get(self,request):
form = self.form_class(None)
return render(request,self.template_name, {"form": form})
#procces form data
def post(self,request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
#cleaned (normalized) data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
#returns User objects if credentials are correct
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request,user)
return redirect('music:index')
return render(request,self.template_name, {"form": form})
and here is my models.py :
from django.db import models
from django.core.urlresolvers import reverse
class Album(models.Model):
artist = models.CharField(max_length=250)
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):
return self.album_title + ' - ' + self.artist
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
file_type = models.CharField(max_length=10)
song_title = models.CharField(max_length=250)
is_favorite = models.BooleanField(default=False)
# song_file = models.FileField(null=True)
def __str__(self):
return self.song_title
def get_absolute_url(self):
return reverse('music:detail', kwargs={'pk': self.album.id})
urls.py:
from django.conf.urls import url
from . import views
app_name = 'music'
urlpatterns = [
# /music/
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^register/$', views.UserFormView.as_view(), name='register'),
# /music/album/54
url(r'^album/(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
# music/album/add
url(r'album/add/$', views.AlbumCreate.as_view(), name='album-add'),
# music/album/3/AddSong
url(r'album/(?P<pk>[0-9]+)/AddSong/$', views.SongCreate.as_view(), name='song-add'),
# music/album/2/update/
url(r'album/(?P<pk>[0-9]+)/AlbumUpdate/$', views.AlbumUpdate.as_view(), name='album-update'),
# music/album/2/delete/
url(r'album/(?P<pk>[0-9]+)/AlbumDelete/$', views.AlbumDelete.as_view(), name='album-delete'),
]
For creating forms I used Django built-in forms,I had to create one for adding albums and another for adding the album's songs
Here is my album_form.html screenshot
and here is my form-template.html screenshot:
and here is my song_form.html screenshot
In the form_valid method, you should fetch the album pk from the url kwargs and set the album on the form instance.
from. django.shortcuts import get_object_or_404
class SongCreate(CreateView):
model = Song
fields = ['song_title', 'file_type']
def form_valid(self, form):
album = get_object_or_404(Album, pk=self.kwargs['pk']
form.instance.album = album
return super(SongCreate, self).form_valid(form)