I cannot add song to specific album using CreateView - django

I am following buckys django tutorial, he explained how to add albums but not song, i want to try adding songs to specific album but it is not working.
I have added a SongCreate view to my views.py, i also created a song_form.html template for inputting song details.I have also tried the form_valid method, but it doesnt just work.
My views.py
class AlbumCreate(CreateView):
model=Albums
fields=['alb_title','alb_genre','alb_logo','alb_artist']
class SongCreate(CreateView):
model = Song
fields = ['song_title', 'song_format']
def form_valid(self, form):
album = get_object_or_404(Albums, pk=self.kwargs['pk'])
form.instance.album = album
return super(SongCreate, self).form_valid(form)
#My urls.py
app_name ='music'
urlpatterns = [
path('',views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('album/add/', views.AlbumCreate.as_view(), name='album-add'),
path('album/<int:pk>/songadd/', views.SongCreate.as_view(),
name='song-add'),
path('album/<int:pk>/', views.AlbumUpdate.as_view(), name='album-
update'),
path('album/<int:pk>/delete/', views.AlbumDelete.as_view(),
name='album-delete'),
]
#My song_form.html template
{% extends 'music/base.html' %}
{% block title %}Add New Song{% endblock %}
{% block body %}
<div class="container-fluid">
<h4>Add the details of the Song in the given fields.</h4>
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="panel panel-default">
<div class="panel-body">
<form class='form-horizontal' action=""
method="post"
enctype="multipart/form-data">
{% csrf_token %}
{% include 'music/form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-
success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
#Models.py
class Albums(models.Model):
alb_title = models.CharField(max_length = 250)
alb_genre = models.CharField(max_length = 250)
alb_logo = models.FileField()
alb_artist = models.CharField(max_length = 250)
def get_absolute_url(self):
return reverse("music:detail", kwargs={"pk": self.pk})
def __str__(self):
return self.alb_title + '-' + self.alb_artist
class Song(models.Model):
song = models.ForeignKey(Albums, on_delete = models.CASCADE)
song_title = models.CharField(max_length = 250)
song_format = models.CharField(max_length = 10)
is_favourite = models.BooleanField(default=False)
def __str__(self):
return self.song_title
def get_absolute_url(self):
return reverse('music:detail', kwargs={'pk': self.song.pk})
When add song is clicked it directs me to a form to fill song detail, but when i tried it i got:
IntegrityError at /music/album/song/add/
NOT NULL constraint failed: music_song.song_id

you must :
def create_song(request):
if request.method == "POST":
form.save()

I give you the way I use form_valid()
def form_valid(self, form):
album = get_object_or_404(Albums, pk=self.kwargs['pk'])
form = form.save(commit=False)
form.album = album
form.save()
return super().form_valid(form)
If it doesn't work, it means you have changes not reflected in your database. Run ./manage.py makemigrations and ./manage.py migrate. It might be necessary, if possible, to drop and recreate the whole db.

Related

'Post' object has no attribute 'get_content_type' in django Photo Blog App

I am really lost and trying to solve this issue for hours. I am working on this social media for photographers, where they can comment each other's photos. I set up forms for comments, but I am getting AttributeError :
'Post' object has no attribute 'get_content_type'
This is my Views.py - photo_detail, where is the error :
def photo_detail(request, id):
instance = get_object_or_404(Post, id=id)
comments = Socialmedia.objects.filter_by_instance(instance)
initial_data = {
"content_type": instance.get_content_type,
"object_id": instance.id
}
socialmedia_form = SocialmediaForm(
request.POST or None, initial=initial_data)
if socialmedia_form.is_valid():
print(socialmedia_form.cleaned_data)
context = {
"title": instance.title,
"photo": instance.photo,
"instance": instance,
"comments": comments,
"socialmedia_form": socialmedia_form,
}
return render(request, "photo_detail.html", context)
When I comment out line "content_type": instance.get_content_type,, the error disaapers, but after writing comment its saying field is required and not posting anything , so it doesnt load the data from comment.
And here is my models.py :
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
from socialmedia.models import Socialmedia, SocialmediaManager
from django.contrib.contenttypes.models import ContentType
def upload_location(instance, filename):
return '%s/%s' % (instance.id, filename)
class Post(models.Model):
# category = models.ForeignKey(Type, blank=True, null=True, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
title = models.CharField(max_length=200)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
time = models.DateTimeField(auto_now=False, auto_now_add=True)
photo = models.ImageField(upload_to=upload_location,
null=True, blank=True,
height_field="height_field",
width_field="width_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("photo_detail", kwargs={"id": self.id})
#property
def get_content_type(self):
instance = self
content_type = ContentType.objects.get_for_model(instance.__class__)
return content_type
And the last page photo_detail.html, where I am trying to implement it.
{% extends "base.html" %}
{% block content%}
<div class="col-sm-8 col-sm-offset-6">
{% if instance.photo %}
<img src="{{ instance.photo.url }}" class="img-responsive"/>
{% endif %}
<h1>{{ title }} </h1>
<p>Author: {{ instance.user}}</p>
<p><div class="fb-like" data-href="https://developers.facebook.com/docs/plugins/" data-width="" data-layout="button" data-action="like" data-size="small" data-share="true"></div></p>
<br>
<p>Updated : {{ instance.updated }}<br/></p>
<p> Created :{{ instance.time }}<br/></p>
<div>
{{instance.comments.all}}
<p class="lead">Comments</p>
<form method="POST" action="."> {% csrf_token %}
{{ socialmedia_form}}
<input type="submit" value="Post" class="btn btn-default">
</form>
{% for comment in comments %}
<div class="">
{{ comment.content }}
{{comment.user}} {{comment.time | timesince }} ago
</div>
{% endfor %}
</div>
</div>
{% endblock %}

Modelset Factory displays a choice fields instead of an input field

Models.py
class Post(models.Model):
title = models.CharField(max_length=100)
conent = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to="post_pics")
def __str__(self):
return self.title
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
class Tag(models.Model):
name = models.CharField(max_length=30)
members = models.ManyToManyField(Post, through='PostTag')
def __str__(self):
return self.name
class PostTag(models.Model):
article = models.ForeignKey(Post, on_delete=models.CASCADE)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
Forms.py
class PostUpdateForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'conent', 'image']
class TagUpdateForm(forms.ModelForm):
class Meta:
model = PostTag
fields = ['tag']
TagUpdateFormSet = modelformset_factory(PostTag, form=TagUpdateForm)
Views.py
#login_required
def updateView(request, pk):
template_name = 'project/post_update.html'
heading_message = 'Tags'
if request.method == 'GET':
form1 = PostUpdateForm(instance=Post.objects.filter(id=pk).first())
form2 = TagUpdateFormSet(queryset=PostTag.objects.filter(article=Post.objects.filter(id=pk).first()))
elif request.method == 'POST':
form1 = PostUpdateForm(request.POST, request.FILES, instance=Post.objects.filter(id=pk).first())
form2 = TagUpdateFormSet(request.POST, queryset=PostTag.objects.filter(article=Post.objects.filter(id=pk).first()))
if form1.is_valid():
invalid = True
for formz in form2:
if formz.is_valid() == False:
invalid = False
break
if invalid:
postform = form1.save(commit=False)
postform.author = request.user
postform.save()
for forms in form2:
data = forms.cleaned_data.get('tag')
if data:
returnedTag, created1 = Tag.objects.get_or_create(name = data)
link, created2 = PostTag.objects.get_or_create(article = postform, tag = returnedTag)
return HttpResponseRedirect('/forum/post/%s/' %(postform.id))
return render(request, 'project/post_update.html', {'form': form1, 'form2': form2})
template
{% extends "template/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% load static %}
<div class="container form-section s-yellow section">
<form method="POST" action="" enctype='multipart/form-data'>
{% csrf_token %}
<fieldset class="form-container">
<legend class="form-top"></legend>
<div class="form1">
{{ form|crispy }}
</div>
<div class="form2 form-group">
{{ form2.management_form }}
{% for formz in form2 %}
<div>
<div class="form-row">
<div class="input-group">
{{formz }}
<div class="">
<button type="button" class="add-form-row">+</button>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</fieldset>
</form>
</div>
{% endblock content %}
I want to let the user be able to edit all tags in a post, however when i display the tags they show up as choice field that lets the user choose from already existing tags and they can't type a new one.
Is there a way to change the choice field to an input field where the original value is the tag originaly entered.
I tried edditing the 'tag' field to a charfield above the meta tag in the form, but then i was getting an input field with the choice field value (eg 4, 6, 10,) instead of the actual text.
I know the saving part doesnt work, but i need to figure out a way to get the fields dispalyed properly
Btw are there any tutorials for a database structure like this? It's hard to find examples where one table links to 2 others.

Django CreateView not able to create model object

I am using Django CreateView on model object. The form gets rendered but on submitting Post button, nothing happens. In console I am receiving code 200 (Success) but object is not created. Also, I am using same HTML template and same code for Update View and it is working perfectly. Please help.
class EventCreateView(LoginRequiredMixin, CreateView):
model = Event
fields = ['name', 'event_attendees']
def form_valid(self, form):
form.instance.creator = self.request.user
return super().form_valid(form)
Model
name = models.CharField(max_length=100)
date = models.DateTimeField(default=timezone.now)
location = models.CharField(max_length=16, choices=EVENT_VENUES, default='sec-1, noida')
event_attendees = models.FileField(upload_to='documents/', default='')
creator = models.ForeignKey(User, on_delete=models.CASCADE)
form_rollout_time = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('event-detail', kwargs={'pk': self.pk})
Html template
{% extends "events/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New Event</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
Urls
urlpatterns = [
path('', EventListView.as_view(), name='event-home'),
path('user/<str:username>', UserEventListView.as_view(), name='user-events'),
path('event/<int:pk>/', EventDetailView.as_view(), name='event-detail'),
path('event/new/', EventCreateView.as_view(), name='event-create'),
path('event/<int:pk>/update/', EventUpdateView.as_view(), name='event-update'),
path('event/<int:pk>/delete/', EventDeleteView.as_view(), name='event-delete')
]
update code like this
def form_valid(self, form):
obj = form.save(commit=False)
obj.creator = self.request.user
obj.save()
try this
Solved the issue by overriding method form_invalid(). Apparently, the issue was in the implementation with FileField but was suppressed with the default implementation of form_invalid. On overriding the method, the actual issue arose.

How input date in my template ListView (request.POST.get) in Django

I have a class jourListView(ListView). I want to input date in my html template and then retrieve the date to make a filter.
My class jourListView(ListView) refers to two linked tables.
I am stuck at level. How to make my code functional?
here are my models, views and template.
class jour(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE, related_name='jour')
date = models.DateField(blank=True, null=True)
commentaire = models.CharField(max_length=500, blank=True, null=True)
class Meta:
managed = False
db_table = 'jour'
unique_together = (('id'),)
verbose_name = 'JOUR'
verbose_name_plural = 'JOUR'
id = models.AutoField(primary_key=True)
def get_absolute_url(self):
return reverse("jour_detail",kwargs={'pk':self.pk})
def __str__(self):
return str(self.date) ##
class activite(models.Model):
jour = models.ForeignKey('blog.jour',on_delete=models.CASCADE, related_name='jour' )
name= models.CharField(max_length=500, blank=True, null=True)
class Meta:
managed = False
db_table = 'activite'
unique_together = (('id'),)
verbose_name = 'ACTIVITÉ'
verbose_name_plural = 'ACTIVITÉ'
id = models.AutoField(primary_key=True)
def __str__(self):
return self.type
def get_absolute_url(self):
return reverse("jour_list")
My view:
class jourListView(ListView):
model = jour
def get_context_data(self, **kwargs):
if request.method == 'POST':
date_insert = request.POST.get('date_ref')
context = super(jourListView, self).get_context_data(**kwargs)
context['count'] = self.get_queryset().count()
return context
def get_queryset(self):
return jour.objects.filter(date__lte=timezone.now()).filter(user=self.request.user).filter(date__in=date_insert)
My html template:
{% if user.is_authenticated %}
<div class="container text-center">
<form class="form-signin" id="login_form" method="post" action="/blog/list/">
{% csrf_token %}
<br>
<input type="date" name="date_ref" class="form-control" placeholder="SAISIE DATE " value="" required autofocus>
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">OK</button>
</form>
</div>
<div class="centerstage">
{% for jour in jour_list %}
<div class="post">
<p class='postcontent' ><strong>Date:</strong> {{ jour.date }}</p>
<p class='postcontent' ><strong>Commentaire:</strong> {{ jour.commentaire }}</p>
<a class="btn btn-primary" href="{% url 'jour_edit' pk=jour.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
<h1>Détails activités</h1>
</div>
-----------------
{% endfor %}
</div>
{% endif %}
I changed my view but it does not work.
class jourListView(ListView):
model = jour
template_name = "blog/list.html"
def get_context_data(self, **kwargs):
if request.method == 'POST':
date_insert = request.POST.get('date_ref')
context = super(jourListView, self).get_context_data(**kwargs)
context['count'] = self.get_queryset().count()
return context
def get_queryset(self):
queryset = jour.objects.filter(date__lte=timezone.now()).filter(user=self.request.user)
date_insert = request.POST.get('date_ref')
if date_insert:
queryset = queryset.filter(date=date_insert)
return queryset
In addition I have another error:
NameError at /blog/list/
name 'request' is not defined
Request Method:
GET
Request URL:
http://127.0.0.1:8000/blog/list/
Django Version:
2.0.2
Exception Type:
NameError
Exception Value:
name 'request' is not defined
You need to define date_insert inside the get_queryset method before you use it. For example:
class jourListView(ListView):
model = jour
def get_context_data(self, **kwargs):
if self.request.method == 'POST':
date_insert = self.request.POST.get('date_ref')
context = super(jourListView, self).get_context_data(**kwargs)
context['count'] = self.get_queryset().count()
return context
def get_queryset(self):
queryset = jour.objects.filter(date__lte=timezone.now()).filter(user=self.request.user)
date_insert = self.request.POST.get('date_ref')
if date_insert:
queryset = queryset.filter(date=date_insert)
return queryset
Once that's working, you may want to consider some further improvements
Renaming the model to Jour to match the Django style
Make sure you return a context in get_context_data for GET requests as well as POST requests.
Using LoginRequiredMixin to make sure that only logged in users can access the view
Adding checks to handle the case where date_insert isn't a valid date string.
I found the solution to my problem.
Here is the result:
I was inspired by the example in this link:
Django: Search form in Class Based ListView
My view:
class jourListView(ListView):
model = jour
template_name = "blog/list.html"
def get_context_data(self, **kwargs):
context = super(jourListView, self).get_context_data(**kwargs)
# FILTER BY CURRENT MONTH, USER
filter_ = jour.objects.filter(date__lte=timezone.now()).filter(user_id=self.request.user).order_by('-date')
if self.request.GET.get('date_ref'):
date_insert = self.request.GET.get('date_ref')
filter_ = filter_.filter(date=date_insert)
context['jourListView'] = filter_
return context
My template (blog/list.html):
{% extends 'blog/base.html' %}
{% block content %}
{% if user.is_authenticated %}
<form class="navbar-form navbar-right" action="." method="get">
{{ form.as_p }}
<input id="date_ref" name="date_ref" type="date" placeholder="Localizar..." class="form-control">
<button type="submit" class="btn btn-success form-control"><span class="glyphicon glyphicon-search"></span></button>
</form>
{% if jourListView %}
{% for select_value in jourListView %}
<div class="post">
<p class='postcontent' ><strong>Date:</strong> {{ select_value.date}}</p>
<p class='postcontent' ><strong>User ID:</strong> {{ select_value.user_id}}</p>
<p class='postcontent' ><strong>Status:</strong> {{ select_value.status}}</p>
</div>
-----------------
{% endfor %}
{% endif %}
{% endif %}
{% endblock %}

Uploading multiple images in Django for a single post

I am beginner in django . I would like to make an application that allows a user to record examinations and related images.
So i try to uploading multiple images in Django for a single post according this topic http://qasimalbaqali.com/uploading-multiple-images-in-django-for-a-single-post/.
But nothing happens when I press the button
I explain my models. A document is a generic class. An exam is a document, a document contains files.
class Document(models.Model):
class Meta:
db_table = 'Document'
slug = models.SlugField(max_length=100)
user = models.ForeignKey(User)
level = models.ForeignKey(ClassLevel, null=False, default=1)
school = models.ForeignKey(School, null=False, default=1)
nb_views = models.IntegerField(default=0)
name = models.CharField(max_length=100)
matter = models.ForeignKey(ClassTopic, null=False, default=1)
status = models.IntegerField(choices=DOCUMENT_STATUS, default=1)
creation_date = models.DateTimeField(auto_now_add=True)
deletion_date = models.DateTimeField(auto_now_add=False, default=None, null=True)
def __unicode__(self):
return self.name + " (" + str(self.status) + ") " + self.school.name
class DocumentFile(models.Model):
class Meta:
db_table = 'DocumentFile'
file = models.FileField(upload_to="photo/", null=True)
document = models.ForeignKey(Document)
def __unicode__(self):
return self.file
class Exam(Document):
class Meta:
db_table = 'Exam'
year_exam = models.IntegerField(choices=EXAM_YEAR_CHOICES, default=1)
mock_exam = models.IntegerField(choices=EXAM_TYPE, default=1)
def __unicode__(self):
return self.name + " " + self.matter
I create two forms. For exam and for file.
class UploadFileForm(ModelForm):
#description = forms.CharField(max_length=30)
file = forms.FileInput()
helper = FormHelper()
helper.form_id = 'file-input'
helper.form_show_labels = False
helper.layout = Layout(PrependedText('file', "", placeholder=""))
#helper.layout.insert(1, HTML("<input type='file' class='file' multiple data-show-upload='false' data-show-caption='true'>"))
class Meta:
model = DocumentFile
fields = ('file',)
#exclude = ("file_type", "file_path", "document")
class CreateExamForm(forms.ModelForm):
helper = FormHelper()
helper.form_id = 'CreateExam'
helper.form_show_labels = False
helper.layout = Layout(
PrependedText("matter", "", ""),
PrependedText("level", "<small class='text-warning'>Selectionner la classe. </small>", ""),
PrependedText("school", "<pre><small>Selectionner l\'établissement. </small></pre>", css_class="selectpicker"),
PrependedText("year_exam", ""),
PrependedText("mock_exam", ""))
class Meta:
model = Exam
exclude = ("slug", "user", "nb_views", "name", "status", "creation_date", "deletion_date")
My view
def createexam(request):
# Creation du formulaire + upload des images
doc_form = CreateExamForm(auto_id=True)
# Création du formset avec n itération : extra=2
file_form_set = modelformset_factory(DocumentFile, form=UploadFileForm, extra=1)
# Récupération du formulaire géré par le mécanisme formset
#formset = sortedfilesform()
if request.method == "POST":
doc_form = CreateExamForm(request.POST)
files_form = file_form_set(request.POST, request.FILES, queryset=DocumentFile.objects.none())
if doc_form.is_valid() and files_form.is_valid():
doc_save = doc_form.save(commit=False)
doc_save.user = request.user
for fileform in files_form.cleaned_data:
image = fileform['file']
one_image = DocumentFile(document=doc_save, file_value=image)
one_image.save(commit=False)
transaction.commit()
msg = FORM_PROPERTIES.FORM_EXAM_STORED.replace("user", request.user.nickname)
messages.add_message(request, messages.SUCCESS, msg)
form = LoginForm()
context = {'form': form}
return render_to_response(template_name='login.html', context=context, context_instance=RequestContext(request))
else:
messages.add_message(request, messages.SUCCESS, FORM_PROPERTIES.FORM_EXAM_ERROR)
context = {'doc_form': doc_form, 'file_form_set': file_form_set, }
return render(request, 'createexam.html', context)
else:
context = {'doc_form': doc_form, 'file_form_set': file_form_set, }
return render(request, 'createexam.html', context)
my url.py
urlpatterns = [
# Examples:
url(r'^$', home, name='home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^$', home),
url(r'^home', home),
url(r'^login', login),
url(r'^logout', logout),
url(r'^register$', register),
url(r'^createexam$', createexam),
url(r'^account/reset_password', reset_password, name="reset_password"),
]
My template is simple
<div id="login-overlay" class="modal-dialog">
<div class="row">
<div class="panel panel-info" >
<div class="panel-heading">
<div class="panel-title">Créer un examen</div>
</div>
<div class="panel-body" >
<div class="col-sm-12">
<form id="post_form" method="POST" action='.'
enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in doc_form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in doc_form %}
{{ field }} <br />
{% endfor %}
{{ file_form_set.management_form }}
{% for form in file_form_set %}
{% crispy form %}
{% endfor %}
<input type="submit" value="Add recipe" class="submit" />
</form>
</div>
</div>
</div>
</div>
Everything seems good form me. But my submit does no think.
I 'm on it for two days.
I read and tried many things. Does anybody can help me please (Sorry for my english)
There are a couple of things wrong here.
Firstly you are not showing the form errors in the template, so the user has no way of knowing why their submission is invalid. Make sure you either do {{ field.errors }} after every field, or do {{ form.errors }} for the whole form at once; and remember to do this both form the main form and the image formset.
Secondly, you're saving the forms with commit=False, so they are not persisted to the database. It's fine to do that if you want to add extra data not included in the form, but you then need to remember to actually persist the object by calling eg doc_save.save().
I solved my problem when i put my main form body in <table> ... </table>
<form id="CreateExamForm" method="POST" enctypr="multipart/form-data">
{% csrf_token %}
<table>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Classe - Matière - Date</h3>
<span class="pull-right"><i class="glyphicon glyphicon-chevron-up"></i></span>
</div>
<div class="panel-body">
{% crispy doc_form %}
{{ file_form_set.management_form }}
{% for f_form in file_form_set %}
<div class="form-inline">
{% crispy f_form %}
</div>
{% endfor %}
</div>
</div>
</table>
<input type="submit" value="Add recipe" class="submit" />
</form>