Ckeditor - user friendly image upload - django

I have ckeditor 4 with image upload on my website. Everything works great the only issue is that it visually looks very bad. Is it possible to style or change the UI for the image upload as I expect users will have a hard time understanding it. I just want a simple upload button nothing fancy
Update:
I discovered the easy image plugin and it does exactly what i need, just a simple image upload button. The issue is it requires a cloud service subscription so it wont work for me.

You can add style and customize the input, one way could be:
{%if field.name == 'picture' %}
<label for ="id_picture" id="icon_upload" class="fa fa-camera"></label>
<input type="file" name="picture" id="id_picture" accept="image/*"style="display: none;" >
{% endif %}
the field name usually is take of the field name model,, but it can change depending on how the form is passed to a template.
https://docs.djangoproject.com/en/3.2/ref/forms/fields/

I used this to remove all the dialog tabs and just kept the image upload tab
CKEDITOR_CONFIGS = {
'default': {
'removeDialogTabs': 'image:advanced;image:Link;image:info',
}

Related

Django i18n language switcher not working on deploy at subdirectory

I've got a site with two languages (it will get more in time) and a little dropdown menu to switch languages. It works as desired/expected in the development server. Urls look like this when visiting the site:
localhost:8000/en/home
localhost:8000/pl/home
The django project gets deployed on a server (Apache w/ mod-wsgi) at a subdirectory location, lets say:
mysite.com/django
Everything works as expected, even the admin site, etc, underneath that subdirectory, however, my little menu to change languages doesn't work anymore. When I change the language, the page reloads, but on the same language that it was on when I tried to change it. I can go back and forth between the languages by manually changing the url in the browser and all the pages work as expected with the translations; it's just the dropdown button that doesn't work anymore.
mysite.com/django/en/home
mysite.com/django/pl/home
At first, I thought it was my button (pretty standard off a tutorial):
<form action="{% url 'set_language' %}" method="post" class="form-inline">{% csrf_token %}
<div class="form-group mx-sm-3 mb-0">
<input type="hidden" name="text" value="{{ redirect_to }}" class="form-control form-control-sm">
<select name="language" id="langselect" onchange="this.form.submit()">
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}" {% if language.code == LANGUAGE_CODE %} selected {% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
</div>
</form>
but actually if I change the Apache config to deploy the site at server root mysite.com (just to try to isolate the problem) the dropdown button, translations, and everything else work as expected. I think this means that somewhere the i18n is generating a bogus link, i.e. it's not implementing the '/django' subdirectory prefix the right way.
I feel like this should be an easy fix —a setting to toggle somewhere— but I'm stumped after spending most of the day googling and reading documentation. I'm happy to share snippets of settings, etc, but honestly, I'm not sure what's relevant.
Could someone please point me in the right direction with a keyword or a suggestion how to solve this?
Edit 1:
I tried to add the prefix to value in the <input> tag. So it read value="/django{{ redirect_to }}" but that didn't work either.
Edit 2 & 4:
Using my switcher button with the network inspector open reveals that the setlang function is calling the wrong url.
mysite.com/django/django/i18n/setlang
I still don't know how to fix it, but I'm fairly certain that's the problem.
If I change the apache config to deploy at mysite.com the redirect is via mysite.com/i18n/setlang, so it seems like I need to somehow control how the django subdirectory prefix is interpreted. But HOW?!?!?
Edit 3:
The switcher successfully changes the cookie, despite not reloading to the proper language.
So after much frustration, I have a working solution.
I had to first create a custom filter that would cut the language code from the url. Since the existing code successfully updated the language preference cookie, and since navigating to any path without a language code automatically / successfully appends the language path, I could redirect with my switcher to a path without the language code and the site will successfully render according to the user's browser preferences or cookie. Cutting out the language code from the url seemed to be the most reasonable way for now.
Add a set up infrastructure for custom template tags according to the documentaiton here. I added a templatetags directory to my app, and inside an __init__.py file and a <myapp>_extras.py file
In my case, I needed to cut the second element from the full url path, so my filter function in <myapp>_extras.py. The file looks like this:
from django import template
register = template.Library()
#register.filter
def custom_redir_lang(url_fullpath):
ls_urls = url_fullpath.split('/')
del ls_urls[1]
return '/'.join(ls_urls)
Then I change the value of the input tag in my template from "{{ redirect_to }}" to "{{ request.get_full_path|custom_redir_lang }}"
Now the site redirects properly underneath the subdirectory prefix.

Load django template dynamically

I've 2 section in my screen. Left section is for showing tabs and right is for displaying that tab template(as shown in screenshot). I'm not able to understand how to load different templates when I click these tabs
For example, when I click change password, I should be able to load change_password.html template
This is by far I've tried with code.
<div class="nav">
<ul>
<li class="active"></i><span class="hidden-xs hidden-sm">Home</span></li>
<li></i><span class="hidden-xs hidden-sm">Change Password</span></li>
<li>Bookings</span></li>
<li></i><span class="hidden-xs hidden-sm">Settings</span></li>
</ul>
</div>
I've tried to use with but no luck.
I've just started with django, so if anything is missed let me know. Thanks for your help!
Screenshot
I think what you're attempting is not possible. If you don't want a page reload upon clicking on a tab, you need to use Javascript to dynamically show/hide elements. If page reload is acceptable, you can create different views for each tab, each view rendering a different html file.
You can use the Django include tag to render another template with the current context. E.g. {% include "foo/bar.html" %} (see documentation here). But this will not solve your problem of displaying different content upon clicking on a tab.

Submit Button Confusion and Request being sent Twice (Using Flask)

I'm pretty much trying to create a web app that takes 2 svn urls and does something with them.
The code for my form is simple, I'm also using WTForms
class SVN_Path(Form):
svn_url=StringField('SVN_Path',[validators.URL()])
I'm trying to create 2 forms with 2 submit buttons that submit the 2 urls individually so my test3.html looks like this:
<form action="" method="post" name="SVNPath1">
{{form1.hidden_tag()}}
<p>
SVN Directory:
{{form1.svn_url(size=50)}}
<input type="submit" value="Update">
<br>
{% for error in form1.svn_url.errors %}
<span style="color: red;">[{{error}}]</span>
{% endfor %}
</p>
</form>
<form action="" method="post" name="SVNPath2">
{{form2.hidden_tag()}}
<p>
SVN Directory:
{{form2.svn_url(size=50)}}
<input type="submit" value="Update">
<br>
{% for error in form2.svn_url.errors %}
<span style="color: red;">[{{error}}]</span>
{% endfor %}
</p>
</form>
MY FIRST QUESTION is how do I know which submit button was clicked so I can run the proper function on the corresponding svn url. I have tried doing something like
if request.form1['submit'] == 'Update':
if request.form2['submit'] == 'Update':
but that does not work at all. I'm new to web dev in general and flask so a detailed explanation would be helpful.
SECONDLY, since submits weren't working properly I also tried an alternative to keep my work moving so in my .py file I have
#app.route('/test3', methods=['GET','POST'])
def test3():
basepath=createDir()
form1=SVN_Path()
form2=SVN_Path()
if request.method=="POST":
if form1.validate_on_submit():
svn_url = form1.svn_url.data
prev_pdf=PDF_List(svn_url,basepath,'prev') #some function
if form2.validate_on_submit():
svn_url2 = form2.svn_url.data
new_pdf=PDF_List(svn_url,basepath,'new') #some function
return render_template('test3.html', form1=form1, form2=form2)
CreateDir is a function that creates a directory in the local /tmp using timestamps of the local time.
Whenever I go the webpage it creates a directory, lets call it dir1, since its calling CreateDir. Thats what I want, but when I click submit on the form it creates another directory dir2 in the tmp folder which is NOT what I want since I want everything to being the same dir1 directory.
In addition when I put a url in one of the forms and click submit, it automatically puts it the same value in the 2nd form as well.
Sorry if this is really long and possibly confusing, but any help is appreciated.
:) Let's see if we can clarify this a little.
To your first question:
As #dim suggested in his comment, You have a few options:
You can submit your form to separate unique urls. That way you know which form was submitted
You can create two similar but different Form classes (the fields will need different names like prev_svn_url and cur_svn_url). This way in your view function, you instantiate two different forms and you'll know which form was submitted based on form.validate_on_submit()
The third option would be to add a name attribute to your submit button and then change the value attributes to something like 'Update Previous' and 'Update Current'. This way in your view function you can check the value of request.data[<submit button name>] to determine if 'Update Previous' was pressed or 'Update Current'.
To your second question:
Multiple directories are being created because you're calling createDir() each time the page is loaded to show the forms and when the forms get posted. In order to create just once, you'll need some kind of logic to determine that the directory was not previously created before calling createDir()
In addition: Since both forms are from the same SVN_Path class, they read post data exactly the same way, that's why whatever you type in form 1 appears in form 2.
Now for my 2 cents:
I assume you're trying to write some kind of application that takes two SVN urls as input, creates a folder and does something with those URLs in that folder. If this is the case, the way you are currently going about it is inefficient and won't work well. You can achieve this with just one form class having 2 svn_url fields (with different names of course) and then handling all of that in one post.
EDIT: The job of the submit button is to tell the browser that you're ready to send the data on the form to the server. In this case you should only need one submit button (SubmitFiled => when rendered). Clicking that one submit button will send data from both input fields to your view function.
Your form should look something like:
class SVN_Path(Form):
prev_svn_url=StringField('Previous SVN_Path',[validators.URL()])
new_svn_url=StringField('New SVN_Path',[validators.URL()])
and your view function:
def test():
form = SVN_Path()
if request.method == "POST":
if form.validate_on_submit():
basepath = createDir() # Only create dir when everything validates
prev_svn_url = form.prev_svn_url.data
new_svn_url = form.new_svn_url.data
prev_pdf = PDF_List(prev_svn_url, basepath, 'prev')
new_pdf = PDF_List(new_svn_url, basepath, 'new')
...
return render_template('test3.html', form1=form1, form2=form2)

Wagtail Image template tags

I'm using Django-variant CMS Wagtail and am trying to build my own templates for it.
I can upload images into the rich text field in Wagtail's CMS as shown:
In my template's html, I would like to be able to call specific images uploaded in the body so that I can style those specific images differently with js.
perhaps something like {{ body.image }}?
the html:
{% extends 'wagweb/base.html' %}
{% load rich_text static compress cache image_tags pageurl %}
{% block content %}
<div class="box">
<article class ="content">
{{ self.body | richtext }}
</article>
</div>
{% endblock %}
I'm lost at this point, as I can't figure out how to find the pre-existing tag dictionary (if there is any) or to create one without messing with the views.py? Or would it be more straight-forward to install markdown into the richtextfield and work from there?
I'm tons more comfortable with html and css, so one solution is to simply write everything in html and use {{ MEDIA_URL }} to call the specific images. But that seems like an unintelligent way to use Wagtail and Django.
Currently the rich text editor doesn't support embedded images with custom attributes (like CSS classes). It also doesn't provide a HTML source editor for the richtext field.
However, if you don't need to have the images inline with the rich text (but rather before or after the text, you could include them in your page model using InlinePanel pointing to table which uses a ParentalKey. Then, in your templates, you could loop through multiple images and apply the specialized CSS classes. The Wagtail demo project uses this method to create an image carousel. You can find some explanation on the more general tactic of using ParentalKey/InlinePanel here in the Editing API.

Using Bootstrap wysiwyg text editor in Django Form

I am using Django and Bootrap 2.32. I want to include this wysiwyg-bootrap-themed text editor: http://mindmup.github.io/bootstrap-wysiwyg/. The usage of this editor is fairly simple, including
$('#editor').wysiwyg();
in the JS-declaration will render each
<div class=editor></div>
into a beatiful wysiwyg text-editor.
Now the problem: I want to include this editor into one of my django form field. I have the single form:
class Article_Form(ModelForm):
Article_text = CharField(widget=Textarea(attrs = {'id' : 'editor'}))
class Meta:
model= Article
, whereas the Article model includes one simple CharField . Is there any chance, to get the editor work inside the Article_text form-field? With the above-mentioned widget, the created textarea cannot be controlled by the wysiwyg-editor-control buttons. Wrapping the form-template-tag like this
<div id="editor">
{{ Article_Form.Article_text }}
</div>
doesn't work either. The problem thus is that Django creates a textarea, wheras the editor would need a <div> to render correctly. Do you guys have any idea how to get this to work (without refering to django-wysiwyg).
Thanks!
I don't know enough about Django but I wrote the editor you're referring to, so here's a suggestion. Assuming the other answer on this page is correct and you can't generate a div directly, you can generate a text area using whatever Django templates you would normally do, then assign two events:
1) page onload event that would copy the textarea contents into the div, something like
$('#editor').html($('#textarea').val())
2) form onsubmit event that would reverse copy the current div contents into the textarea before it gets submitted
$('#textarea').val($('#editor').html())
Take a look at this.
Summernote is a simple WYSIWYG editor based on Twitter's Bootstrap.
django-summernote plugin allows you to embed Summernote into your Django admin page very handy.
https://github.com/lqez/django-summernote
Are you sure that this "plugin" doesn't work with textarea?
{{ Article_Form.Article_text }}
will be rendered to something like:
<textarea cols="40" id="id_Article_text" name="Article_text" rows="10"></textarea>
So there is a chance that you can initialize the wysiwyg editor like:
$('#id_Article_text').wysiwyg();
However after checking the plugin, I doubt that would be possible since it is using contenteditable="true" attribute of HTML5 and probably the plugin works with div only.
So there is no way you can make it work natively with Django form. The solution should be display other fields of your form manually, hide the one with textarea and display the editor instead:
<form action="" method="POST">
{{ Article_Form.field1 }}
{{ Article_Form.field2 }}
<div class=editor></div>
{% csrf_token %}
<input type="submit" value="Submit" id="submit-btn" />
</form>
Then you can use JS to submit your form:
$('#submit-btn').click(function (e) {
e.preventDefault();
$.ajax({
// do your magic here.
// note that you can get the content of the editor with: $('#editor').cleanHtml();
})
});
This way is hackish I agree so I don't recommend you go for it, just find other plugin then. Also please read PEP 8 carefully.
Hope it helps.
Take a look at this repo: https://github.com/rochapps/django-secure-input
I think it solves most of your problems.