django_quill modelform QuillField does not render in form - django

I cannot seem to get QuillField to render in my form. Every other field renders just fine. I cannot find what I am missing here.
I have gone over django_quill_editor oficial docs and scoured google. I am at a loss.
UPDATE: After removing and re-migrating the Model from scratch QuillField renders in Admin, but not still not in template.
Here are the files.
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.sites',
'crispy_forms',
'blog',
'django_quill',
forms.py
from .models import UserPost
class UserPostForm(forms.ModelForm):
class Meta:
model = UserPost
fields = ('title', 'image', 'content')
models.py
from django_quill.fields import QuillField
class UserPost(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=500)
image = models.ImageField(upload_to='images/', blank=True, null=True)
categories = models.ManyToManyField('Category', related_name='userposts')
content = QuillField()
date_published = models.DateField(auto_now_add=True)
url = models.SlugField(max_length=500, unique=True, blank=True, editable=False)
def save(self, *args, **kwargs):
self.url = slugify(self.title)
super(UserPost, self).save(*args, **kwargs)
views.py
from .forms import UserPostForm
def userposts_create_view(request):
form = UserPostForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.save()
return redirect("landingpage:home")
context= {'form': form,}
return render(request, 'userpost_create.html', context)
userpost_create.html
{% load crispy_forms_tags %}
<div class="card">
<div class="card-title">
<h1>Create Post</h1>
</div>
<div class="card-body">
<form enctype="multipart/form-data" method="POST" action="">
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-6 mb-0">
{{ form.title|as_crispy_field }}
</div>
<div class="form-group col-md-6 mb-0">
{{ form.image|as_crispy_field }}
</div>
</div>
{{ form.content }}
<input type="submit" value="Post"/>
</form>
</div>

Related

Why is the Django form not rendering in a class-based view?

Background: I've been working on the 'mini blog' challenge in Mozilla's tutorial. Got 'author' (user), 'post' working. Added 'comment'. With bits of code from this (among others), I managed to use a function-based view to get 'CommentForm' work on the 'post-detail' page. But trying to convert the function-based view to a class-based view stumped me. Because the various errors I encountered all relate to some key fundamental concepts, like explicit/implicit 'request', passing 'context', I've been working at it, hoping to understand Django better. But I'm getting nowhere. The problem is the form, 'CommentForm', doesn't render in the template. At one point, it rendered, but 'submit' the form led to not allowed error. I figured it related to 'GET' vs 'POST'. At this point, I'm not sure where the issue is--views? template? Appreciate some pointers.
Here's my code:
models.py
class Post(models.Model):
post = models.TextField(max_length=1000)
post_title = models.CharField(max_length=100)
description = models.TextField(max_length=500)
post_created_at = models.DateTimeField(auto_now_add=True)
post_updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, related_name="posts", on_delete=models.CASCADE)
#property
def num_comments(self):
return Comment.objects.filter(post_connected=self).count()
def __str__(self):
return f'{self.author or ""} – {self.post_title[:40]}'
def get_absolute_url(self):
return reverse('post-detail', args=[str(self.id)])
def get_absolute_url(self):
return "/blog/{}/".format(self.pk)
class Meta:
ordering = ['-post_created_at']
class Comment(models.Model):
comment_title = models.CharField(max_length=100)
comment = models.TextField(max_length=1000)
comment_created_at = models.DateTimeField(auto_now_add=True)
comment_updated_at = models.DateTimeField(auto_now=True)
commenter = models.ForeignKey(User, related_name="commented", null=True, blank=True, on_delete=models.CASCADE)
active = models.BooleanField(default=False)
post_connected = models.ForeignKey(Post, related_name='comment', on_delete=models.CASCADE, default=None, null=True) #
class Meta:
ordering = ['comment_created_at']
def __str__(self):
return str(self.commenter) + ' : ' + self.comment_title[:40]
def get_absolute_url(self):
return reverse('post-detail', args=[str(self.id)])
### function-based views.py (clumsy, but the form renders and saves)
def post_detail(request, pk):
template_name = 'post_detail.html'
post = get_object_or_404(Post, pk=pk)
comments = post.comment.filter(active=True)
new_comment = None
# Comment posted
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post_connected = post
new_comment.save()
return redirect('/')
else:
comment_form = CommentForm()
return render(request, 'post_detail.html', {'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})
### function-based template (everything works):
<div class="col-md-8 card mb-4 mt-3 ">
<div class="card-body">
<!-- comments -->
<h2>{{post.num_comments}} comments:</h2>
{% for comment in comments %}
<div class="comments" style="padding: 10px;">
<p class="font-weight-bold">
{{ comment.comment_title }} - {{comment.commenter}}
<span class=" text-muted font-weight-normal">
{{ comment.comment_created_at }}
</span>
</p>
{{ comment.comment | linebreaks }}
</div>
{% endfor %}
</div>
</div>
<div class="col-md-8 card mb-4 mt-3 ">
<div class="card-body">
<h3>Leave a comment</h3>
<form method="post" style="margin-top: 1.3em;">
{{ comment_form.as_p }}
{% csrf_token %}
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
</form>
</div>
</div>
urls.py (for both views, I comment out the url (and view) not in use)
urlpatterns += [
path('blog/<int:pk>/', views.post_detail, name='post_detail'),
#path('blog/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
]
Same models.py, but class-based view:
### Class-based view (form doesn't get rendered at all)
class PostDetailView(generic.DetailView):
# pass
model = Post
form_class = CommentForm
def post_detail_view(self, request, primary_key):
post = get_object_or_404(Post, pk=primary_key)
post_connected = Comment.objects.filter(
post_connected=self.get_object()).order_by('-comment_created_at')
comments = post_connected
return comments
def get_success_url(self):
return reverse('post-detail', kwargs={'pk' : self.object.pk})
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(PostDetailView, self).get_form_kwargs(
*args, **kwargs)
return kwargs
if self.request.user.is_authenticated:
comment_form = CommentForm()
comment_form = CommentForm(instance=selfrequest.user)
new_comment = CommentForm(request.POST)
new_comment.save()
def get_object(self):
post = super().get_object()
post_connected = Comment.objects.filter(
post_connected=self.get_object()).order_by('-comment_created_at')
if self.request.user.is_authenticated:
self.request.user = CommentForm(instance=self.request.user)
comment = CommentForm(request.POST)
comment.save()
post.author = User.objects.filter(id=post.author.id)
post.views +=1
post.save()
return post
The code for the templates is identical for both views, but the files are in different directories:
<div class="col-md-8 card mb-4 mt-3 ">
<div class="card-body">
<!-- comments -->
<h2>{{post.num_comments}} comments:</h2>
{% for comment in comments %}
<div class="comments" style="padding: 10px;">
<p class="font-weight-bold">
{{ comment.comment_title }} - {{comment.commenter}}
<span class=" text-muted font-weight-normal">
{{ comment.comment_created_at }}
</span>
</p>
{{ comment.comment | linebreaks }}
</div>
{% endfor %}
</div>
</div>
<div class="col-md-8 card mb-4 mt-3 ">
<div class="card-body">
<h3>Leave a comment</h3>
<form action="{% url 'post-detail' post.id %}" method="POST" style="margin-top: 1.3em;">
{{ comment_form.as_p }}
{% csrf_token %}
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
</form>
</div>
</div>

Forms Django Python

Could someone help me?
I don't know what I'm doing wrong. I try to change ma value in database but it doesn't work. Still it is the same like it set default.. Below my codes...Thank You in advance.
koszyk.html
{% for produkt in produkty%}
<div id="bin">
<div class ='name'>{{ produkt.nazwa }}</div> <div class="product_price">
{{ produkt.cena }} {{ produkt.ilosc }}
<form method="POST">
{% csrf_token %}
{{ form }}
<button type="submit" href ="{% url 'numbers' produkt.id %}">zaktualizuj</button>
</form>
</div>
<div class="delete"> Usuń</div>
{% endfor %}
models.py
class Basket(models.Model):
nazwa = models.CharField(max_length=64, blank=False, unique=True, default="")
cena = models.PositiveSmallIntegerField(default=2000)
opis = models.TextField(default="")
ilosc = models.PositiveSmallIntegerField(default=3)
forms.py
from django.forms import ModelForm
from .models import Shop, Basket
class IloscForm(ModelForm):
class Meta:
model = Basket
fields = ['ilosc',]
views.py
def numbers(request, id):
form = IloscForm(request.POST or None)
produkt = Basket.objects.get(pk=id)
if form.is_valid():
ilosc = form.save(commit=False)
produkt.ilosc = ilosc
ilosc.save()
return redirect('koszyk')
def koszyk(request):
produkty = Basket.objects.all()
form = IloscForm()
return render(request, 'koszyk.html', {'produkty': produkty, 'form':form})
I would be very grateful for help!
Natalia
You're not saving the changes to produkt. Instead you are saving ilosc.
Change
ilosc.save()
to
produkt.save()

I cannot add song to specific album using CreateView

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.

Django blog post doesn't update it just creates another object

This view is supposed to find a blog post and change it's information, but instead of that it just makes a new Blog object with the new (and old) information.
The update view
#login_required
def view_updatepost(request, blog_id):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
#post = Blog.objects.get(pk=blog_id)
post_to_be_changed = get_object_or_404(Blog, pk=blog_id)
form = BlogForm(request.POST or None, instance=post_to_be_changed)
if form.is_valid():
post_to_be_changed = form.save(commit=False)
#
#
post_to_be_changed.save()
#messages.success(request, "<a href='#'>Item</a> Saved", extra_tags='html_safe')
return HttpResponseRedirect(post_to_be_changed.get_absolute_url())
context = {
'post_to_be_changed': post_to_be_changed,
'form': form,
}
return render(request, 'blog/makepost.html', context)
The template used by the view makepost.html
{% extends "base.html" %}
{% load staticfiles %}
{% block main_content %}
<!-- Page Header -->
<!-- Set your background image for this header on the line below. -->
<header class="intro-header" style="background-image: url('{% static "img/about-bg.jpg" %}')">
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<div class="page-heading">
<h1>Make a Post</h1>
<hr class="small">
<span class="subheading">Share with the World.</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
{% if not user.is_authenticated %}
You must be <u>logged in</u> to make a post.
{% else %}
<form action="{% url "makepost" %}" method="post">
{% csrf_token %}
{{form.as_p}}
<div align="center">
<input class="btn btn-default" type="submit" value="Post to Blog" onclick="window.location='{% url "" %}';"/>
{# Home #}
</div>
</form>
{% endif %}
</div>
</div>
</div>
<hr>
{% endblock main_content %}
The models.py
from django.db import models
import datetime
# Create your models here.
class Blog(models.Model):
title = models.CharField(max_length=250)
subtitle = models.CharField(max_length=250, null = True, blank=True)
date_added = models.DateTimeField(default=datetime.datetime.now())
image = models.TextField(max_length=1000, null = True, blank=True)
tags = models.TextField(max_length=500, null=True, blank=True)
article = models.TextField(max_length=15000, null=True, blank=True)
author = models.CharField(max_length=150, null=True, blank=True)
def get_absolute_url(self):
return "/blog/%i" % self.pk
The forms.py
from django import forms
from .models import Blog
import datetime
class PostForm(forms.Form):
title = forms.CharField()
subtitle = forms.CharField(required=False)
date_added = forms.DateTimeField()
image = forms.URLField(required=False)
tags = forms.CharField(required=False)
article = forms.CharField()
author = forms.CharField()
class BlogForm(forms.ModelForm):
class Meta:
model = Blog
fields = ('title', 'subtitle',
'image', 'tags', 'article')
It seems that you are not referring to your update view in your form action url:
<form action="{% url **"makepost"** %}" method="post">

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>