Enable markdown to render text submitted from a form - django

When employ the bootstrap in Django to format the form, it display nicely.
{% for entry in entries %}
<div class="panel panel-default">
<div class="panel-heading">
<h3>
{{ entry.date_added|date:"M d, Y H:i"}}
<small>
<a href="{% url 'learning_logs:edit_entry' entry.id %}">
edit entry</a>
</small>
</h3>
</div>
<div class="panel-body">
{{ entry.text|linebreaks}}
</div>
</div> <!-- panel -->
However, it can only render my submitted data in plain text like:
How to enable markdown to render the text in Django?

Related

Customize the style of a django.forms.BooleanField() containing a django.forms.CheckboxInput()

I included a contact-form on my webpage which looks like so:
I would like to style the "CC myself" - checkbox in the following ways:
The text "CC myself" is centered vertically within its box.
The checkbox should be right next to the text "CC myself".
The "forward"-symbol should be between text and checkbox, but directly next to the text and with more horizontal distance to the checkbox (on its right-hand side).
This is how I defined the contact form in forms.py:
from django import forms
class ContactForm(forms.Form):
# * Sender
from_email = forms.EmailField(
required=True,
label='Your Email',
widget=forms.TextInput(attrs={'placeholder': 'jsmith#example.com'}))
# * Optional CC to sender
cc_myself = forms.BooleanField(
required=False,
label='CC myself',
widget=forms.CheckboxInput(attrs={'class': 'fa fa-share'}))
# * Subject
subject = forms.CharField(required=True, label='Subject')
# * Message
message = forms.CharField(
widget=forms.Textarea(attrs={'placeholder': 'Dear Andreas ..'}),
required=True,
label='Message')
In the home.html template then, the form is displayed like so:
<form style="margin-left: auto;margin-right: 0;" method="post" action="{% url 'contact' %}">
{% csrf_token %}
<!-- * Neat autoformatting of the django-form via "pip install django-widget-tweaks"
Docs: https://simpleisbetterthancomplex.com/2015/12/04/package-of-the-week-django-widget-tweaks.html -->
{% for hidden in sendemail_form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in sendemail_form.visible_fields %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field|add_class:'form-control' }}
{% for error in field.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
{% endfor %}
<div style="text-align:center" class="form-actions">
<button type="submit" class="btn btn-success">
<!-- Search icons: https://fontawesome.com/icons?s=solid (syntax: class="fa fa-name-of-icon"))
Docs on how to implement: https://stackoverflow.com/questions/32612690/bootstrap-4-glyphicons-migration/41281304#41281304-->
<span class="fa fa-paper-plane"></span> Send Message
</button>
<!-- Add horizontal space: https://stackoverflow.com/questions/31198170/want-to-add-spacing-between-buttons/31199399#31199399 -->
<!-- Add cancel-button redirecting to "home" according to the following docs: https://simpleisbetterthancomplex.com/2015/12/04/package-of-the-week-django-widget-tweaks.html -->
<a href="{% url 'home' %}" class="btn btn-secondary">
<span class="fa fa-times"></span> Cancel
</a>
</div>
</form>
Edit on CSS-styling (bootstrap 4.x) employed in my project:
In my base.html wrapped around all my templates, the following is included:
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Docs for including fontawesome: https://stackoverflow.com/a/41281304/12298276 -->
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
Edit after trying out the first suggestion of #Danoram:
The result looks like this (only modification is the place of the "forward" - symbol inside the checkbox:
I would like to display the help_text='Decide if the message should be forwarded to you.' below the checkbox in grey, just like with the other fields. Also, the checkbox is still much bigger regarding its height compared to the label text "CC myself". And last but not least, the formatting of the entire contact-form column has gotten distorted. Especially the latter should be fixed, otherwise I can't implement it this way.
This was my best attempt (conserving the size of the checkbox).
Using an if check to render the cc field separately.
Although to do this I had to remove the classes from the checkboxinput and put them directly into the html
forms.py
cc_myself = forms.BooleanField(
required=False,
label='CC myself',
widget=forms.CheckboxInput())
home.html
<form style="margin-left: auto;margin-right: 0;" method="post" action="{% url 'contact' %}">
{% csrf_token %}
<!-- * Neat autoformatting of the django-form via "pip install django-widget-tweaks"
Docs: https://simpleisbetterthancomplex.com/2015/12/04/package-of-the-week-django-widget-tweaks.html -->
{% for hidden in sendemail_form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in sendemail_form.visible_fields %}
{% if field.label == 'CC myself'%}
<div class="row form-group">
<div class="col-3 col-lg-2 col-xl-auto">
<label>{{ field.label }} <label for="{{ field.id_for_label }}" class="fa fa-share"></label></label>
</div>
<div class="col-2">
{{ field|add_class:'form-control' }}
</div>
</div>
{% else %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field|add_class:'form-control' }}
{% for error in field.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
{% endif %}
{% endfor %}
<div style="text-align:center" class="form-actions">
<button type="submit" class="btn btn-success">
<!-- Search icons: https://fontawesome.com/icons?s=solid (syntax: class="fa fa-name-of-icon"))
Docs on how to implement: https://stackoverflow.com/questions/32612690/bootstrap-4-glyphicons-migration/41281304#41281304-->
<span class="fa fa-paper-plane"></span> Send Message
</button>
<!-- Add horizontal space: https://stackoverflow.com/questions/31198170/want-to-add-spacing-between-buttons/31199399#31199399 -->
<!-- Add cancel-button redirecting to "home" according to the following docs: https://simpleisbetterthancomplex.com/2015/12/04/package-of-the-week-django-widget-tweaks.html -->
<a href="{% url 'home' %}" class="btn btn-secondary">
<span class="fa fa-times"></span> Cancel
</a>
</div>
</form>

How can I use Django inline formset with Bootstrap-select plugin?

I've been trying to use the Django inline formset with the bootstrap-select plugin from here https://developer.snapappointments.com/bootstrap-select/ and every other thing works perfectly, I'm able to successfully call the plugin on another two selects that I have in my form and I'm using the inline formset to add new authors on my book. When i put the "selectpicker" class, it only works once, when the page is loaded, but when I press the button to add more authors, the select field is not loaded.
So I have a question... can I use the two together? If yes, how? If not, is there any workaround to be able to search in a selection field?
Bellow is a image to how my form looks when i press the big green "Add" button at the end of the form.
You can see that there is only two fields, one less than the first one.
If any code is needed, please let me know and i will add right away.
Thanks!
EDIT:
Here are my codes, as asked by Chris:
My template:
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block content %}
{% load static %}
<form method="POST" class="form" action="">
{% csrf_token %}
[other fields]
...
<!-- HERE I HAVE MY TWO OTHER SELECT FIELDS WHICH WORK PERFECTLY -->
<div class="container">
<div class="col-sm-12">
<div class="form-group">
<div class="row">
<div class="col-sm-6">
<label>Editora do Livro:</label>
{{ form.editora_cod_editora|add_class:"selectpicker form-control"|attr:"data-live-search='true'" }}
</div>
<div class="col-sm-6">
<label>Categoria do Livro:</label>
{{form.categoria_cod_categoria|add_class:"selectpicker form-control"|attr:"data-live-search='true'" }}
</div>
</div>
</div>
</div>
</div>
<!-- HERE START MY ONLINE FORM, AS SHOWS THE PRINT -->
<div class="container">
<div class="col-sm-12">
<hr>
<h4>Adicionar Autor</h4>
<hr>
<div class="form-group bg-light rounded ">
{{ autor_livro.management_form }}
{% for form in autor_livro.forms %}
<div class="{% cycle 'row1' 'row2' %} formset_row m-5 inline-form">
{{ form.autor_cod_autor|add_class:"selectpicker form-control"|attr:"data-live-search='true'" }}
{{ form.ordinal_autorlivro|add_class:"form-control" }}
{{ form.autor_funcao|add_class:"form-control" }}
</div>
{% endfor %}
</div>
</div>
<div class="container">
<div class="col-sm-12">
<div class="form-group">
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-4">
<button type="submit" class="btn-outline-primary btn float-right">Salvar</button>
</div>
</div>
</div>
</div>
</div>
</form>
{% block scripts %}
<!-- HERE I HAVE MY SCRIPT THAT MAKES THE INLINE FORM WORK WITH THAT PLUGIN -->
<script src="{% static 'js/jquery.formset.js' %}"></script>
<script type="text/javascript">
$('.formset_row').formset({
addText: 'Adicionar Autor',
deleteText: 'Remover',
prefix: 'autorlivro_set'
});
</script>
{% endblock %}
{% endblock %}
The answer is the behaviour of the bootstrap-select plugin. You are activating it by using the class "selectpicker". After loading the page some javascript magic takes the elements with the class selectpicker and creates the widget you see. The "select" you now see is not your original <select> but an auxillary widget, your <select> is still there but hidden from your view.
Now when you add another form the javascript magic is not called again, so that you get a new form where your <select> is hidden somewhere from the user's eyes.
In order to get it rendered nicely again you need to run the required javascript after you have added a new form. django-dynamic-formset provides an option called added allowing you define a function which is called after the new form has been added. Form more details see the formset options here.
So define the function and call it after adding a form. In your case your script could look like this:
<script type="text/javascript">
var activate_select = function(row){
row.find('.selectpicker').selectpicker();
};
$('.formset_row').formset({
addText: 'Adicionar Autor',
deleteText: 'Remover',
prefix: 'autorlivro_set,
added: activate_select
});
</script>

Django Variable Wrapped in Paragraph Tag

I am using django-ckeditor as a WYSIWYG text editor when creating posts. It captures and saves the content and the correct HTML tags without any problem. However, my template renders the variable surrounded by <p> tags, which ruins the RichTextField because <p> tags cannot be nested. As a result, it was showing all of the text (with tags) as a paragraph with no formatting. I realized that this was happening, so I changed the surrounding tags in my template to <div> tags, but when the template is loaded on the browser, it replaces the div tags with paragraph tags again. How can I get rid of the <p> tags so that my text is rendered with the correct formatting?
Here is my template:
{% extends 'bandwagon/base.html' %}
{% block content %}
<article class="media content-section">
<img src="{{ post.author.profile.image.url }}" alt="profile photo" class="rounded-circle article-img">
<div class="media-body">
<img src="{{ post.image.url }}" class="post-img">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted | date:'F d, Y'}}</small>
{% if object.author == user %}
<div>
Edit
Delete
</div>
{% endif %}
</div>
<h2 class='article-title-detail'>{{ object.title }}</h2>
<div class="article-content">{{ object.content | safe }}</div>
</div>
</article>
{% endblock content %}
However, in the browser, the response is this:
<p class="article-content"><h3>Fake Content</h3>
<h3><span style="font-size:13px">Fake Content</span></h3></p>
By default CKEditor RichTextField adds <p> tags around the content of the field.
If that's the reason you keep seeing <p> around your content, you can customizing your CKEditor editor, so it will not add the <p> like this:
#base.py
CKEDITOR_CONFIGS = {
'default': {
'autoParagraph': False
},
}
You can also create a specific configuration and set specific fields to use it.
read more about it here: https://django-ckeditor.readthedocs.io/en/latest/#optional-customizing-ckeditor-editor

How can I pass an image ID from the view into my routes.py, when the images are displayed in the view via a for loop?

I'm building a simple portfolio website where the owner will be able to manage a gallery page, Adding, Editing and Removing posts. I am printing the images from the DB using a for loop and need a way in order to get either the name of the image or the ID of the image and send the value back to the route in order to delete the row from the DB. Any suggestion would be much appreciated.
Additional information:
Using Flask w/ SQLalchemy & WTforms
Sample of how I'm displaying the images and accompanying data:
{% for image in Posts | reverse %}
<div class="row pt-3">
<div class="col">
<img class="img-fluid rounded" src="static/gallery_images/{{image.image }}" alt="">
</div>
</div>
<div class="row pt-4">
<div class="col">
<h3 style="display: inline">{{image.title}}</h3>
<p class="font-italic text-muted" style="display: inline">
{% if image.sold_flag %}
- Sold
{% else %}
- Available
{% endif %}
</p>
<p class="text-muted">{{image.date_posted.strftime('%d/%m/%Y')}}</p>
</div>
</div>
<div class="row">
<div class="col">
<p class="font-weight-normal">{{ image.description }}</p>
</div>
</div>
<div class="row">
{% if current_user.is_authenticated %}
<div class="col text-left">
<button type="button" class="btn btn-dark">Edit</button>
<button type="button" class="btn btn-danger">Delete</button>
</div>
{% endif %}
</div>
<hr class="border">
{% endfor %}
There are multiple ways to store the id and use it for a route call. Using purely what you have shared, you can add a call to the button to the respective endpoints:
Assuming you have a method images.delete(id) to delete images and that you want to keep with the button tag on your code:
<a href={{url_for('delete.edit', id=image.id)}}>
<button type="button" class="btn btn-dark">
Delete
</button>
</a>
However, I would really recommend for you to use a form to submit the delete, as opposed to a GET request generated above. This way you can have it secured with WTForm CSRF token.
Example:
HTML
<form action="{{url_for('delete.edit', id=image.id)}}" method="POST" role="form">
{{ form.hidden_tag() }}
</form>
Python
## Make sure to create the delete form
class DeleteImage(Form):
pass

Django Bootstrap Grid all content breaks onto new line

I am building a website using the Django framework where it will display a grid of places (3 per row) however the code below, every place ends up going onto a new line within the column.
<div class="site-container container-fluid">
<div class="row">
<div class="col-md-3 col-lg-2">
<div class="thumbnail">
<a href="{% url 'sites:details' site.id %}">
<img src="{{ site.site_picture}}" class="img-responsive">
</a>
<div class="caption">
<h2>{{ site.site_name }}</h2>
<h4>{{ site.site_street }}</h4>
<!-- View Details -->
View Details <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
</div>
</div>
</div>
</div>
</div>
In my browser I see the content I want however every site is on a new line in the column, whereas I would like it to be in a row of three and break onto a new line and then begin another row of three.
Screenshot
I think it is because you are executing all within the
<div class="col-md-3 col-lg-2">
If you inspect the browser do you see only one of these elements? If so then that would be your problem. What you want is something like,
<div class="site-container container-fluid">
<div class="row">
LOOP OUTSIDE OF HERE!!!!!!!! <---------------------
<div class="col-md-3 col-lg-2">
<div class="thumbnail">
<a href="{% url 'sites:details' site.id %}">
<img src="{{ site.site_picture}}" class="img-responsive">
</a>
<div class="caption">
<h2>{{ site.site_name }}</h2>
<h4>{{ site.site_street }}</h4>
<!-- View Details -->
View Details <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
</div>
</div>
</div>
That way you will get multiple columns each holding its own content.