Hello, I'd like to know how can I use CKEditor inside Django crispy forms.
I've installed django-ckeditor and registered it inside INSTALLED_APPS
It does work for admin area, but I also have a Post create/ Post update forms on frontend where it doesn't work at all.
Since I'm using crispy forms, I've created a forms.py file which looks like this:
from .models import *
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field, Submit
class PostUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PostUpdateForm, self).__init__(*args, **kwargs)
# form helper function
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.field_class = 'form-group'
self.helper.layout = Layout(
Field('title', css_class="form-control", placeholder='Post title'),
Field('content', css_class="form-control", placeholder='Post content'),
Field('category', css_class="form-control"),
Field('image', css_class="form-control"),
Field('tag', css_class="form-control", placeholder='tag1, tag2', value=self.instance.post_tag())
)
self.helper.add_input(Submit('submit', 'Update Post', css_class='btn btn-underline-primary'))
tag = forms.CharField()
class Meta:
model = Post
fields = ['title', 'content', 'category', 'image']
According to this example I've imported RichTextField from ckeditor.fields module, but I have no idea how to use it with crispy forms.
The view I'm using is this:
@method_decorator(login_required(login_url='users/login'), name='dispatch')
class PostUpdateView(UpdateView):
model = Post
template_name = 'posts/update.html'
form_class = PostUpdateForm
def get_success_url(self):
return reverse('detail', kwargs={'slug': self.object.slug})
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.tag.clear()
tags = self.request.POST.get('tag').split(',')
for tag in tags:
current_tag = Tag.objects.filter(slug=slugify(tag))
# check if tag already exists
if current_tag.count() < 1:
new_tag = Tag.objects.create(title=tag)
form.instance.tag.add(new_tag)
else:
existing_tag = Tag.objects.get(slug=slugify(tag))
form.instance.tag.add(existing_tag)
return super(PostUpdateView, self).form_valid(form)
# only user who created a post can update it
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if self.object.user != request.user:
return HttpResponseRedirect('/')
return super(PostUpdateView, self).get(request, *args, **kwargs)
On frontend I display the form like this:
<h3 class="text-center mb-5 mt-0 pt-0">Update Post</h3>
{% if user.is_authenticated %}
{% crispy form %}
{% else %}
<div class="mt-5">
<!-- link to login/register -->
</div>
{% endif %}
Can anyone provide a solution to this problem or some guidance?
Update:
This is my Post model:
class Post(models.Model):
title = models.CharField(max_length=150, unique=True)
content = models.TextField()
publish_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(blank=True, null=True, upload_to='uploads/')
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(default="slug", editable=False)
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1, related_name='posts')
tag = models.ManyToManyField(Tag, related_name='posts', blank=True)
slider_post = models.BooleanField(default=False)
hit = models.PositiveIntegerField(default=0)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def __str__(self):
return self.title
def post_tag(self):
return ', '.join(str(tag) for tag in self.tag.all())
def comment_count(self):
return self.comments.all().count()
Update 2:
What I did so far:
#settings.py:
INSTALLED_APPS += [ 'ckeditor', 'ckeditor_uploader' ]
CKEDITOR_UPLOAD_PATH = 'uploads/' # to set the uploads directory
# urls.py:
urlpatterns = [
path('ckeditor/', include('ckeditor_uploader.urls'))
]
#update.html template file
{% load crispy_forms_tags %} {# for crispy form #}
{{ form.media }}
{% crispy form %}
After I've changed the model according to mr. Scott's sugestion, everything is ok.
I hope you are adding ckeditor on content field, if yes why cant you change the field in model itself rather than changing in form.
Like below,
This way, your models forms can use it in your form as it is. And in your html base file add the below script tag in <head> section,
Hopefully this should work for your requirement.