How to make sef image link with uploaded tinymce in django? - django

I published my django site but everyday i am finding new problems :)
Today i realised my images in the article has no slugify link.
Forexample in this page https://www.endustri.io/monokristal-gunes-paneli-nedir-calisma-prensibi-avantajlari/
my tinymce settings is
{
"height": 500,
"entity_encoding": "raw",
"menubar": "file edit view insert format tools table help",
"plugins": 'print preview paste importcss searchreplace autolink autosave save code visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists wordcount imagetools textpattern noneditable help charmap emoticons quickbars',
"toolbar": "fullscreen preview | undo redo | bold italic forecolor backcolor | formatselect | image link | "
"alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | fontsizeselect "
"emoticons | ",
"custom_undo_redo_levels": 50,
"quickbars_insert_toolbar": False,
"file_picker_callback": """function (cb, value, meta) {
var input = document.createElement("input");
input.setAttribute("type", "file");
if (meta.filetype == "image") {
input.setAttribute("accept", "image/*");
}
if (meta.filetype == "media") {
input.setAttribute("accept", "video/*");
}
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
var id = "blobid" + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(",")[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
};
input.click();
}""",
"content_style": "body { font-family:Roboto,Helvetica,Arial,sans-serif; font-size:14px }",
}
And i found these codes
'images_upload_handler': 'function(blobInfo, success, failure) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open("POST", "/path/to/upload/handler");
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failure("HTTP Error: " + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != "string") {
failure("Invalid JSON: " + xhr.responseText);
return;
}
success(json.location);
};
formData = new FormData();
formData.append("file", blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
}',
I added these codes to my actual codes but i recieve an error like this.
This image has url like this.
How can i make this image url like endustri.io/(image or media)/image-name.webp
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAApQAAAGVCAMAAAB3pZE2AAAC2VBMVEXz8/Tz8/QoKCktLS4iQX0iRYI6OjwgNmz///8xMTMhQ38hSIchSoo2NjdYWFohPnchOnIhQn5/f4EhR4W+H3DMzM6mpqchRYQhSIYiRoPI0eEhRIJeXl9iYmTX19fIz97p6eoAAACbnaBuRO/Wi/Sf2N27f+CaPUOkapdYxS6xil1jFKrWOUWscotY5Rah2j1DpGqXWMUusYpdb5AlujV99XpgrKAAAAAElFTkSuQmCC

You receive these errors because the value of the property 'images_upload_handler' (Line 187) is a JavaScript function that extends over several lines. This JavaScript function is a multi line string, like the JavaString function in Line 161 for the property 'file_picker_callback'. You have to treat the JavaScript function in Line 187 the same way. Write in Line 187
'images_upload_handler': """function( ...
and at the end of the JavaScript functino in Line 208
}""",
For further Details on multiline strings in Python see https://stackoverflow.com/a/10660443/5655611
Per default, TinyMCE stores images as data URL. This URL contains the data of the whole image. That's why the URL is so long. With data URLs it is possible to embed images directly into HTML. So you can save text, formatting and images i.e. all data of a single document in a single HTML file. That also has advantages.
To save the images separately:
Use images_upload_url instead of images_upload_handler. That is easier.
If you configure an images_upload_url, a file upload function is already integrated in Tiny Mce. I.e. you don't need file_picker_callback.
That means you can use the following for your Tiny Mce settings
{
"height": 500,
"entity_encoding": "raw",
"menubar": "file edit view insert format tools table help",
"plugins": 'print preview paste importcss searchreplace autolink autosave save code visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists wordcount imagetools textpattern noneditable help charmap emoticons quickbars',
"toolbar": "fullscreen preview | undo redo | bold italic forecolor backcolor | formatselect | image link | "
"alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | fontsizeselect "
"emoticons | ",
"custom_undo_redo_levels": 50,
"quickbars_insert_toolbar": False,
"content_style": "body { font-family:Roboto,Helvetica,Arial,sans-serif; font-size:14px }",
"images_upload_url": "upload-file",
}
In order for the url upload-file to work, you have to make following adjustments:
Settings.py:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Urls.py:
urlpatterns = [
...
path("upload-file", views.upload_file, name="upload_file"),
...
]
Views.py:
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from slugify import slugify
import os
import json
import urllib.parse
#csrf_exempt
def upload_file(request):
file= request.FILES['file']
filename= file.name
filenameParts= os.path.splitext(file.name)
slugifiedFilename= slugify(filenameParts[0]) + filenameParts[1]
osFilename= os.path.join(settings.MEDIA_ROOT, slugifiedFilename)
with open(osFilename, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
url= urllib.parse.urljoin( settings.MEDIA_URL, slugifiedFilename)
data= json.dumps( {"location": url})
return HttpResponse( data, content_type='application/json')
Attention:
Beware of the #csrf_exempt. It could be a security risk. See the django documentation for further information.

Related

In R_Shiny, How to integrate an "animated gif" using renderImage with the "download report" example

I would like to:
Click a Button to "Generate Report"
Start an animated gif, showing "Computing ..."
Begin long computation using an Rmd file that generates and downloads an HTML report and
Stop the animated gif.
I can do both independently but not in the desired sequence. Need help. Here is my code in two files:
Shiny code
library(shiny)
library(here)
here::here()
ui <- pageWithSidebar(
headerPanel("How to intgrate an animated gif using renderImage with download report example"),
sidebarPanel(
downloadButton("report", "Generate report")
),
mainPanel(
imageOutput("myImage") # this is a placeholder for image
)
)
server <- function(input, output, session) {
output$myImage <- renderImage({
outfile = here::here("www", "Computing2.gif")
# write(outfile, "outfiledup.gif")
# outfiledup = here::here("outfiledup.gif")
# outfiledup
#
# Return a list containing the filename
list(src = outfile,
contentType = 'image/gif',
width = 125,
height = 50,
alt = "This is alternate text")
}, deleteFile = FALSE) # TRUE)
input_file = "report.Rmd"
output_file = "report.html"
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = output_file, # "report.html", default filename of downloaded file
content = function(file) {
# Copy the report file to a temporary directory before processing it, in
# case we don't have write permissions to the current working dir (which
# can happen when deployed).
tempReport <- file.path(tempdir(), input_file) # "report.Rmd")
file.copy(input_file, tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
# params <- list(n = input$slider)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
shinyApp(ui, server)
here is my report.Rmd file.
---
title: "Report"
author: "ABC DEF"
date: "Aug, 2022"
output: html_document
---
params:
n: = NA
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.
When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
summary(cars)
Including Plots
You can also embed plots, for example:
plot(pressure)
Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.

TinyMCE in Wagtail/Django project doesn't save some of the rich text features, like font size, alignments

I have a Django/Wagtail project. The project uses wagtailtinymce package.
The TinyMCE looks great and it shows fine in all rich text fields and stream blocks.
The Problem
When I change the font size and save it. It is back to normal size as soon as the page refresh. so it doesn’t save the font size, and some other features too.
However, it only saves a few features, like headings.
Here is some code I have:
requirements.txt
...
wagtail==2.11.3
Django==2.2.16
wagtailtinymce # git+https://github.com/TwilioDevEd/wagtailtinymce.git
...
urls.py
path('tinymce/', include('tinymce.urls')),
###settings
INSTALLED_APPS = [
...
'tinymce',
'wagtailtinymce'
]
WAGTAILADMIN_RICH_TEXT_EDITORS = {
'default': {
'WIDGET': 'wagtaildashboard.models.MyTinyMCE'
},
}
wagtaildashboard.models.MyTinyMCE
from django.db import models
# Create your models here.
from django.utils import translation
from wagtailtinymce.rich_text import TinyMCERichTextArea
from django.conf import settings
class MyTinyMCE(TinyMCERichTextArea):
#classmethod
def getDefaultArgs(cls):
return {
"passthru_init_keys": {
'mode': 'textareas',
'plugins': 'preview importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons',
'editimage_cors_hosts': ['picsum.photos'],
'menubar': 'file edit view insert format tools table help',
'toolbar': 'undo redo | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor removeformat | pagebreak | charmap emoticons | fullscreen preview save print | insertfile image media template link anchor codesample | ltr rtl',
'toolbar_sticky': True,
'autosave_ask_before_unload': True,
'autosave_interval': '30s',
'autosave_prefix': '{path}{query}-{id}-',
'autosave_restore_when_empty': False,
'autosave_retention': '2m',
'image_advtab': True,
'template_cdate_format': '[Date Created (CDATE): %m/%d/%Y : %H:%M:%S]',
'template_mdate_format': '[Date Modified (MDATE): %m/%d/%Y : %H:%M:%S]',
'height': 600,
'image_caption': True,
'quickbars_selection_toolbar': 'bold italic | quicklink h2 h3 blockquote quickimage quicktable',
'noneditable_class': 'mceNonEditable',
'toolbar_mode': 'sliding',
'contextmenu': 'link image table',
'content_style': 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
},
}
def __init__(self, *args, **kwargs):
super(MyTinyMCE, self).__init__(*args, **kwargs)
Any solution for this problem?

Can't change "heading 1" font name using docx

I am using the following script :
header = self.document.add_paragraph(style='Heading 1')
header.style.font.name = 'Arial'
header.style.font.size = Pt(16)
header.add_run('Header One')
The result is that "Header One" get 'Calibri'.
This is a legitimate bug even with python-docx version 0.8.5. If you were to change the font name of the style 'Normal', it works (as shown in the examples on the python-docx manuals), but this does not work for the 'Heading 1' style.
One workaround is to create a new heading style that takes Heading 1 as a base style and then modify the new style's font name & size:
from docx.enum.style import WD_STYLE_TYPE
styles = self.document.styles
new_heading_style = styles.add_style('New Heading', WD_STYLE_TYPE.PARAGRAPH)
new_heading_style.base_style = styles['Heading 1']
font = new_heading_style.font
font.name = 'Arial'
font.size = Pt(16)
self.document.add_paragraph('Header One', style='New Heading')

Django audiofield

I am using audiofield in my Django application to allow upload of a .wav file and render it for play.
I am able to succesfully implement it for one upload at a time, showing the player for a single uploaded file
The code is :
def bottom_player(self):
if self.a_file:
file_url = settings.MEDIA_URL + str(self.a_file)
Html5_string = '<div style="position:fixed; top:5em; right:5em; height: 5em; background-color:white;"><audio controls><source src="%s" type="audio/mpeg">%s Your browser does not support the audio element.</audio><br><h3>Audio player will adjust to your screen</h3></div>' % (file_url, os.path.basename(self.a_file.name))
return Html5_string
bottom_player.allow_tags = True
Now, I want to show separate player for multiple uploaded files, so I have created another table having a_file field for upload and a SQL trigger to copy the newly created a_file field value to the previous a_file column in comma separated format
audio-file-NACHY-1698934831.wav, ./audio-file-ABGYT-1890930931.wav
To parse this a_file column values and then show player for each path, the code looks like:
def bottom_player(self):
if self.a_file:
audiolist = self.a_file
filenamelist = audiolist.split(",")
filenamelist
for filename in filenamelist:
file_url = settings.MEDIA_URL + str(filename)
Html5_string += '<div style="position:fixed; top:5em; right:5em; height: 5em; background-color:white;"><audio controls><source src="%s" type="audio/mpeg">%s Your browser does not support the audio element.</audio><br><h3>Audio player will adjust to your screen</h3></div>' % (file_url, os.path.basename(self.filename))
return Html5_string
bottom_player.allow_tags = True
I get "None" in my bottom player field in the Django page.

Django video streaming and Safari HTML5 canvas

I'm streaming small videos from django view:
def play(request):
filename = settings.VIDEO_URL + extra_path
wrapper = FileWrapper(file(filename, "rb"))
response = HttpResponse(wrapper)
response['Content-Type'] = 'video/mp4'
response['Content-Length'] = os.path.getsize(filename)
return response
And have html code like this:
<video style="display: inline-block; width:500px; height:700px;">
<source type="video/mp4" src="play?v=1111">
<video>
Everything works fine, but i need to get video screenshot from JS for drawing above the video frame in canvas. I'm using it:
var video = document.querySelector('video');
var canvas = document.getElementById('canvas-bg');
var context = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
context.fillRect(0, 0, w, h);
context.drawImage(video, 0, 0, w, h);
It works good in Chrome, but i always getting empty context in Safari after context.drawImage(...).
Before django i used php script, like in this link: Streaming an mp4 through a php file progressively, and safari well worked.
Also if i'm changing:
<source type="video/mp4" src="play?v=1111">
to:
<source type="video/mp4" src="/static/video/myfunnyvideo.mp4">
I can get video context in safari! Why? Can anyone help me please.
Don't know why it happens, maybe some http headers are wrong, but I've found other solution for nginx server (for Apache you can use XSendFile):
def play(request):
extra_path = "myfunnyvideo.mp4"
filename = settings.VIDEO_URL + extra_path
response = HttpResponse(mimetype='video/mp4')
response['Accept-Ranges'] = 'bytes'
response['X-Accel-Redirect'] = filename
return response
and in nginx config (/etc/nginx/sites-available/your-site):
location /videos/ {
internal;
alias /var/www/some-folder/protected-folder;
}