Can't use CKEDITOR in django template - python

I am using a form without a model class.
class ClubWallForm(forms.Form):
title = forms.CharField(label='Post title', max_length=100)
description = RichTextField()
imgURL = forms.CharField(label='Post image url', max_length=100)
filefield = forms.FileField( label='Select a file',validators=[validate_file_extension] )
In my template I used
` {% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}`
CKEDITOR is not geting displayed in my template.
This is what I am getting.
Inside my views it tried to use ipdb and found that the form has only fields title imgurl and filefield .

You have two issues:
RichTextField is a model field. RichTextFormField is the corresponding form field.
You're not handling the form media in the template. This is outlined in the documentation.

You can also use widget tweaks
First install it by
pip install django-widget-tweaks
then load it in your template file with
{% load wiget_tweaks %}
also use this in your site header
<script src="https://cdn.ckeditor.com/4.16.1/standard/ckeditor.js"></script>
now you can set your class to your form with out change it in forms.py
so the themplate file should be like this
{{ form.description|add_class:"ckeditor" }}
Second way is:
just use this code in themplate file
{{ form.media }}
{{ form.description }}

Finally I got an answer from my friend.
it was to replace
description = RichTextField()
with
description = forms.CharField(label='Description',
widget=forms.Textarea(attrs={'class': 'ckeditor'}))
inside forms.py
and it is working

Related

How do I use django templates to get a field from the parent object of a model?

I'm trying to create an interface where students can match with other students in the class for a group project based on shared interests and I have a queryset in a django view and from there I am able to use select_related to get the parent object and even print the fields in Anaconda Prompt (when running on local server) but I can't seem to get the field to show up in a template...what am I missing?
Here is the relevant part of my models file:
class Profile(models.Model):
first_nm = models.CharField(max_length=100)
last_nm = models.CharField(max_length=100)
class Potential(models.Model):
user1 = models.ForeignKey(Profile, related_name='user1', on_delete=models.CASCADE)
user2 = models.ForeignKey(Profile, related_name='user2', on_delete=models.CASCADE)
Here is the relevant part of my view:
def matches(request):
my_user = request.user
my_id = Profile.objects.get(slug=my_user)
the_matches = Potential.objects.filter(Q(user1=my_id) | Q(user2=my_id)).all().select_related('user1','user2')
print(the_matches.values())
print(the_matches.values('user2__first_nm'))
return render(request,'projects/matches_list.html', { 'matches':the_matches})
Here is the relevant part of the template:
{% for match in matches %}
<div class="matches">
<p>{{ match.user1__first_nm }}</p>
<p>{{ match.user2__first_nm }}</p>
</div>
{% endfor %}
In the template above, why does this not work?
Thanks in advance!
I have tried using the syntax above like:
<p>{{ match.user2__first_nm }}</p>
and when just printing to the console I get
<QuerySet [{'user2__first_nm': 'test_nm'}]>
from the second to last line in the view above but when I run locally, the html shows up with p tag with no contents. What am I doing wrong?
Thanks!
Do not use __ in template, but use .
__ is only used when constructing QuerySets. In your template, you're accessing the Profile object, so to get an attribute from that object you use the syntax object.attribute.
Your code becomes:
{% for match in matches %}
<div class="matches">
<p>{{ match.user1.first_nm }}</p>
<p>{{ match.user2.first_nm }}</p>
</div>
{% endfor %}

Can you use a regular expression in a Django template conditional?

Is it possible to determine if a template variable in a Django template satisfies a regular expression? In the following template, I want to set the CSS class for the paragraph tag that contains the help text based on whether or not the help text for that field satisfies a regular expression. Here is the template with some pseudocode thrown in:
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
{% if field.help_text|lower (BEGINS WITH SOME STRING) %} # Pseudocode
<p class="select-help-text">{{ field.help_text|safe }}</p>
{% else %}
<p class="help-text">{{ field.help_text|safe }}</p>
{% endif %}
{% endif %}
</div>
{% endfor %}
For example, if the help_text as defined in the associated form starts with the text string "Hold down Ctrl", then the CSS class should be set to select-help-text, otherwise it should just be set to help-text.
I understand that Django regular expressions are based on Python regexes, but Python regex evaluations always seems to be done using the re module which isn't accessible in a Django template. I also looked through the Django documentation but couldn't find a way to do this.
UPDATE
I still can't get this code to work.
Melvyn, who answered below, is technically correct. You should avoid putting conditional logic in Django templates. To that end, I changed my template per the Django documentation:
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help-text">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
I then added an __init__ method to my forms ModelForm class that looks at the label for the form fields that shouldn't have their help text displayed and sets help_text to a "falsey" value so the condition in the template will fail:
def __init__(self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
if visible.field.label == 'foo' or visible.field.label == 'bar' or visible.field.label == 'baz':
visible.field.help_text = False
However, I'm still seeing the help text whether I set help_text to False or None or an empty string. Is this some type of timing issue or have I made a mistake that I'm just not seeing?
DTL (Django Template Language) is not meant to program. In fact, I wouldn't even write a template tag for this. In your view (or form, or field or widget), you have all the power to change the help text to a 2-tuple or dict with a label, so why don't ya ;)
Perhaps the best approach is in the field or widget and just add the desired class to the widget based on the help text.
Overriding model form fields
So, to provide the answer for the update, this is the trimmed down example I used:
models.py
from django.db import models
class Sensor(models.Model):
color = models.CharField(
max_length=20, verbose_name="visible", help_text="Colors are visible"
)
sound = models.CharField(
max_length=20, verbose_name="audible", help_text="Sounds are audible"
)
forms.py
class BasicModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for visible in self.visible_fields():
normalized = visible.label.lower()
if "audible" == normalized:
visible.help_text = ""
class Meta:
model = Sensor
fields = "__all__"
tests.py
from django.template import Template, Context
class FormTest(TestCase):
def test_modelform(self):
form = BasicModelForm()
self.assertEqual(form["sound"].help_text, "")
def test_template(self):
form = BasicModelForm()
context = Context({"form": form})
template = Template("{{ form.sound.help_text }} | {{form.color.help_text}}")
actual = template.render(context)
self.assertEqual(""" | Colors are visible""", actual)
It failed before normalizing the label value. I used the test to have PyCharm break at the assignment, but it never got to the assignment, so then I braked at the if statement to see "Audible" instead of "audible".

Showing a list of database entries

I want to show a list of the names of my database entries. These entries are of type FileField().
I am trying to show them in my html but nothing appears.
Models.py
class UploadedFile(models.Model):
the_file = models.FileField()
Views.py
class Showing_File(ListView):
model = UploadedFile
template_name = 'index.html'
context_object_name = 'the_uploaded_files_list'
index.html
{% for file in the_uploaded_files_list %}
<h1> {{ file.the_file }} </h1>
{% endfor %}
basically FileField is a file type soo you have to add .url in the end to show the file in template
<h1> {{ file.the_file.url }} </h1>

WTForms: nested form field, UndefinedError: 'unicode object' has no attribute 'label'

My form model is defined like this:
from com.example.cms.forms import FieldList as MyAppFieldList
from flask_wtf import Form
from wtforms import fields
from wtforms import validators
class FacebookPostTranslationForm(Form):
language = fields.StringField('Language', [validators.InputRequired(), validators.Length(min=2, max=2)])
title = fields.TextAreaField('Title', [validators.InputRequired()])
description = fields.TextAreaField('Description', [validators.InputRequired()])
linkUrl = fields.StringField('Link', [validators.InputRequired(), validators.URL()])
pictureUrl = fields.StringField('Picture', [validators.InputRequired(), validators.URL()])
class FacebookPostTemplateForm(Form):
name = fields.StringField('Name', [validators.InputRequired()])
title = fields.TextAreaField('Title', [validators.InputRequired()])
description = fields.TextAreaField('Description', [validators.InputRequired()])
linkUrl = fields.StringField('Link', [validators.InputRequired(), validators.URL()])
pictureUrl = fields.StringField('Picture', [validators.InputRequired(), validators.URL()])
translations = MyAppFieldList(fields.FormField(FacebookPostTranslationForm), [validators.Optional()])
class FacebookPostTemplateCreateForm(FacebookPostTemplateForm):
pass
class FacebookPostTemplateUpdateForm(FacebookPostTemplateForm):
pass
and then inside HTML template I have:
<span id="translationFieldsetHolder">
{% for translation in form.translations.entries %}
<fieldset class="translationFieldset">
<legend>{% if translation.language.data %}{{ translation.language.data|upper }}{% else %}Add{% endif %} Translation</legend>
{{ render_field(translation.language) }}
{{ render_field(translation.title, rows=5) }}
{{ render_field(translation.description, rows=5) }}
{{ render_field(translation.linkUrl) }}
{{ render_field(translation.pictureUrl) }}
{{ translation.csrf_token }}
</fieldset>
{% endfor %}
</span>
Everything but translation.description renders fine. Namely this line causes problems:
{{ render_field(translation.description, rows=5) }}
If I replace description with title it works fine (although it renders title twice instead of title plus description).
With description I get the following error:
{{ field.label(class="control-label") }}
UndefinedError: 'unicode object' has no attribute 'label'
in the macro that starts with:
{% macro render_field(field) %}
<div class="control-group {% if field.errors %}error{% endif %}">
{{ field.label(class="control-label") }}
I'm quite new to Python or WTForms. Is there anything special with description field name that could cause some problems / clashes?
I can see that the data is correctly delivered to the controller via the web service. There is nothing suspicious in the value of this field.
The sample code to be run. It was extracted from the original sources so at some places it is a mess.
If I change the name of the field it works :(
But it implies I would have to either change it on the web service or somewhere in Python code.
Thank you.
Field itself has description kwarg
class Field(object):
def __init__(self, label=None, validators=None, filters=tuple(),
description='', id=None, default=None, widget=None,
_form=None, _name=None, _prefix='', _translations=None):
What you are doing is adding into FormField(Field) object that also has description inside
class FacebookPostTranslationForm(Form):
description = fields.TextAreaField('Description', [validators.InputRequired()])
In template when You call translation.description WTForms is returning Field.description instead of FacebookPostTranslationForm.description
Hope that helps :)

Get only one field from django forms in template

I have one form :
class FormLogin(forms.Form):
email = forms.EmailField(max_length=150)
name = forms.CharField(max_length=20)
How can I put just email field in my template ?
I tried this :
{{ form.fields.email }}
But it returns <django.forms.fields.CharField object at 0x00000000043BCEB8>.
You can just use:
{{ form.email }}
You don't need to use fields.
Use:
{{ form.email }}

Categories

Resources