Write contents of ace.js editor to file in Django - python

I am playing around with the idea of editing my Django templates from the server. I know this is a far shot from that but I wrote this bit of code:
def editor(request):
handle=open(os.path.join(settings.BASE_DIR, 'app/code/test.html'), 'r+')
var=handle.read()
context = {
"message": "editor",
"code": var
}
return render(request, 'app/editor.html', context)
That reads a file and passes it's contents to the template where ace.js displays it in the editor.
<div id="editor-container">
<div id="editor">{{code}}</div>
</div>
It displays just fine and I can edit the text, but if I wanted to save my edits, writing them to the file, the button would need to go to a save route because I'm not using ajax, but how would I pass the new version of the document to the view to be written to the file?

To make this work you need to have an hidden input. Whenever the contents of the editor are updated, the input is also update. Saving the contents is just now a matter of submitting the form. Here is what I came up with.
First is the html template where the editor is.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ace editing</title>
<style type="text/css" media="screen">
#editor {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.editor-container {
position: relative;
height: 300px;
width: 100%;
}
</style>
</head>
<body>
<div class="editor-container">
<div id="editor">
{{code}}
</div>
</div>
<form method="POST">
{% csrf_token %} {{form.as_p}}
<button type="submit">Save</button>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
<script>
var editor = ace.edit('editor');
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/html");
editor.on('change', function() {
code_hidden_input = document.querySelector('#id_code');
code_hidden_input.value = editor.getValue();
console.log(editor.getValue())
})
</script>
</body>
</html>
Now in your views.py the code will be like the following.
from django.shortcuts import render
from .forms import MyForm
import os
from django.conf import settings
# Create your views here.
def index(request):
form = MyForm()
handle = open(os.path.join(settings.BASE_DIR, 'core/templates/core/test.html'))
code = handle.read()
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
print(form.cleaned_data['code'])
# This is the part where you save the code you have
# edited to some file
context = {
'form': MyForm(),
'code': code
}
return render(request, "core/index.html", context)
In your forms.py file create a class called My Form like below
from django import forms
class MyForm(forms.Form):
code = forms.CharField(max_length=10000, widget=forms.HiddenInput())
That's all, note when submiting html using forms you need to sanitize your input.

Related

How can I style a django form with css?

I tried looking for the answer earlier but couldn't seem to figure out a few things. I'm creating my form in a form.py file so its a python file.
Here is my forms.py file :
class UploadForm(ModelForm):
name = forms.TextInput(attrs={'class': 'myfieldclass'})
details = forms.TextInput()
littype = forms.TextInput()
image = forms.ImageField()
class Meta:
model = info
fields = ["name", "details", "littype", "image"]
Here is my views.py function for it if it helps find the solution :
def uploadform(request):
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
print(request.FILES)
if form.is_valid():
form.save()
redirect(home)
return render(request, 'uploadform.html', {'form': UploadForm})
To style it I thought I could do something like this which I found in another question :
class MyForm(forms.Form):
myfield = forms.CharField(widget=forms.TextInput(attrs={'class': 'myfieldclass'}))
Except I have no idea how to link a css page to that python file. This is what I tried writing but i think it doesnt work because its meant for html but its in a python file :
<link type="text/css" rel="stylesheet" href="templates/form.css">
And so I'm just not sure how to style my form. Thanks for any answers!
Within your template you have to just import the css file in the head tag, but do ensure you load static first.
html file:
{% load static %}
<!doctype html>
<html lang="en">
<head>
# import the css file here
<link rel="stylesheet" href="{% static 'path to css file' %}">
</head>
...
</html>
Within the css file:
# Styling the class
.myfieldclass{
width: 30% !important;
height: 100px !important;
...
}
But please note that you don't have to import a css file since you can add the style tag in the head tag as well. For example:
<!doctype html>
<html lang="en">
<head>
<style type="text/css">
.myfieldclass{
width: 30% !important;
height: 100px !important;
...
}
</style>
</head>
...
</html>
You could apply css from the python file itself as well.
Approach from the python file.
# Custom way to set css styling on a form field in python code
def field_style():
styles_string = ' '
# List of what you want to add to style the field
styles_list = [
'width: 30% !important;',
'height: 100px !important;',
]
# Converting the list to a string
styles_string = styles_string.join(styles_list)
# or
# styles_string = ' '.join(styles_list)
return styles_string
class MyForm(forms.Form):
myfield = forms.CharField(widget=forms.TextInput(attrs={'class': 'myfieldclass', 'style': field_style()}))
# 'style': field_style() .... field_style() will return in this case 'width: 30% !important; height: 100px !important;'
Any of those should work but I do recommend doing the styling from the hmtl or css file instead.
class StocksForm(forms.Form):
stocks = forms.CharField(
label="",
widget=forms.TextInput(
attrs={
"class": "special",
"size": "40",
"label": "comment",
"placeholder": "Comma Seperated eg - Reliance, Steel, Acrysil.. ",
}
),
)
Template side
{% load static %}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="{% static '/css/cards.css' %}">
the stylesheet has got CSS
as
.special{
font-variant: small-caps;
}
This is how django will render the form with the class, and the styling class will be taken from stylesheet
Hope this helps! :)
You can just include the CSS in the template header like any other stylesheet
Thanks
My standard template uses Django block structure so I can group page-specific CSS with its page.
{% extends "base.html" %}
{% block content %}
my html ...
{% endblock %}
{% block extracss %}
{{block.super}}
<style>
... page-specific CSS
</style>
{% endblock %}
Base.html contains an empty block definition
{% block extracss %}{% endblock %}
which serves to locate the block with other site-wide CSS.

Uploading file to website with android - site cant be reached

I am trying to upload a file in a website using the django framework. When i use my laptop i have no problem at all, but when trying to upload the exact same file with my android device i get 'This site cant be reached'
The problem happens when i click the submit button. I can normally access the main.html with my android device and can even access the get_post/ url without POST if i dont click the button. But when it is clicked i get 'This site cant be reached'
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.core.files.storage import default_storage
from .Uploaded_files import C_Convert as conv
from django.utils.datastructures import MultiValueDictKeyError
def main_view(request):
return render(request, 'main.html')
def get_file(request):
if request.method == 'POST':
print(1)
try:
uploaded_file = request.FILES['file']
except MultiValueDictKeyError:
return HttpResponse('<h1>Error</h1>')
default_storage.save('CSD_Project/Uploaded_files/'+uploaded_file.name, uploaded_file)
result = conv.convert(uploaded_file.name)
return HttpResponse('<h1>%s</h1>'%result)
else:
return HttpResponse('<h1>Error</h1>')
urls.py
from django.contrib import admin
from django.urls import path
from .views import get_file,main_view
urlpatterns = [
path('admin/', admin.site.urls),
path('', main_view),
path('get_file/', get_file) ]
main.html
<!DOCTYPE html>
<html lang="en" style = "background-color: darkslategrey">
<head>
<meta charset="UTF-8">
<title>HY100 Tests</title>
</head>
<body>
<div style="text-align: center;">
<form action="get_file/" method="POST" enctype=multipart/form-data>
{% csrf_token %}
<input type="file" name="file">
<button style="color: white; background-color: #222222; padding: 15px 32px; font-size: 15px;" class="button">Submit file</button>
</form>
</div>
</body>
</html>

AJAX GET request successful; Django View updated but HTML does not get updated

This has completely stumped me and I have stared at the screen for a long time now.
It is about a mail app that I am trying to develop. I have an HTML page that is divided in three parts. Left side has the ability to check/uncheck folders from which to view emails. Middle page "should" show all the mails (depending upon what is selected on the left column). The right most column is expanded view of individual mail in the middle.
I added AJAX GET request feature to pass to view which folders have been selected or unselected. The view gets the AJAX request all right (in the code below I print out args and it is right what I want it to be). However the HTML page/template never responds to the changing args!! I don't know why? Please help me locate the bug in my program.
urls.py
from django.conf.urls import url
from . import views
app_name="Home"
urlpatterns = [
url(r'^$', views.Home_View.as_view(),name="Home"),
url(r'^RightBody/$', views.RightBody, name="RightBody"),
url(r'^RulePopUp/$', views.RulePopUp_View.as_view(), name="RulePopUp"),
]
views.py
class Home_View(View):
def get(self, request):
ExcludedFolder = request.GET.getlist('UncheckedFolder[]')
LeftSide_FolderHandle = FolderTree("/SomePath/")
LeftSide_Folder = LeftSide_FolderHandle.CreateFolderNames()
LeftSide_Folder = LeftSide_FolderHandle.MakeAJSONtree()
CompleteMailBox_Handle = MailLogger("/SomePath/",FoldersToExclude=ExcludedFolder)
CompleteMailBox = CompleteMailBox_Handle.RecreateMailBox()
# RightMail = FullMailInTheRight()
args = {"CompleteMailBox":CompleteMailBox,
"LeftSide_FolderStructure":LeftSide_Folder}
print(args) ##This works
return render(request,'Home_Query.html',args)
Home_Query.html
<!DOCTYPE html>
{% load static %}
<html>
<head>
<meta charset="utf-8">
<title>Main Page</title>
<script type="text/javascript" src="{% static 'js/jquery-3.2.1.js' %}"></script>
<link rel="stylesheet" href="{% static 'css/HomePageMain.css' %}" type="text/css">
</head>
<body>
<h1 class="Headline"> Mail checking app </h1>
<br>
<br>
<div class="left-column">
Select folders to display messages
<br>
<br>
{% include "Home_Query_LeftSide.html" with LeftSide_FolderStructure=LeftSide_FolderStructure %}
</div>
<div class="middle-column">
Select Message to show complete mail on the right
<br>
<br>
{% for eachMail in CompleteMailBox %}
<div class="SingleMail">
<span class="EachMailSender"> Sender: </span> <span class="MailSender">{{eachMail.0.Sender}}</span>, <span class="EachMailTime">Time: </span> <span class="MailTime">{{eachMail.0.Time}}</span> <br>
<span class="EachMailSubject">Subject: </span> <span class="Subject">{{eachMail.0.Subject}}</span><br>
<span class="EachMailBody"> Mail: </span>{{eachMail.1}}
<div class="Rules">
<p id="Rules">Click here for rules</p>
</div>
</div>
{% endfor %}
</div>
<div class="right-column">
This column shows the complete email when selected in the middle column
<br>
<br>
<div class="FullMail">
</div>
<br>
<br>
</div>
</body>
<script type="text/javascript" src="{% static 'js/main.js' %}"></script>
</html>
main.js
var Unchecked = [];
$(function () {
$("input:checkbox").click(function(){
$(this).parent().find("input[type='checkbox']").prop('checked',$(this).is(':checked'));
if ($(".left-column").find("input:checkbox:not(:checked)").length != 0){
var UncheckedFolder = "";
$(this).parent().find("input:checkbox:not(:checked)").each(function(){
UncheckedFolder += "/"+String($(this).prop("id"));
});
if ($.inArray(UncheckedFolder, Unchecked) === -1) {Unchecked.push(UncheckedFolder)}
var CheckedFolder = "";
$(this).parent().find("input:checkbox:checked").each(function(){
CheckedFolder += "/"+String($(this).prop("id"));
});
if ($.inArray(CheckedFolder, Unchecked) != -1) {Unchecked.splice($.inArray(CheckedFolder,Unchecked),1);}
UncheckedFolder = "";
}
else {
Unchecked = [];
}
console.log(Unchecked);
$.ajax({
type: 'get',
url: "/Home/",
datatype: "json",
data: {
'UncheckedFolder':Unchecked,
},
success: PrintMessage,
});
});
});
function PrintMessage(data,textStatus,jqXHR){
console.log("Success To Exclude");
}
Many thanks!
You are close. Return a JsonResponse instead of render:
from django.http import JsonResponse
class Home_View(View):
def get(self, request):
...
print(args) ##This works
return JsonResponse(args)
The javascript call is expecting a response in json format. With render you are returning an HTML template.

How do I use a datepicker on a simple Django form?

Before you mark this as a duplicate to the most famous django datepicker question on SO, hear me out. I have gone through all the questions in the first ten pages of the search results, but no one seems to be explaining anything from the beginning.
What I am looking for is the most simple way to have a datepicker on my form, I don't know if the most simple way is importing it from Admin or using an existing jQuery thing, but whatever it is, can someone please explain step by step like you would do to a baby? This, I believe will help any new programmer like me out there who's looking to learn. This is what I have so far.
My Form:
class SampleForm(forms.Form):
date_of_birth = forms.DateField(label='Enter Date')
My View:
def dlp_test(request):
form = SampleForm()
return render(request, 'dlp_test.html', {'form': form})
My Template:
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
This is the most simple setup anyone can start from, how do I take it from here? When someone clicks on the datefield in the HTML, I want a calendar to pop up so that they can select a date.
If achieving this requires me to have locally stored JS or jQuery files, I'd prefer the URL be embedded in the HTML, rather than downloading and then mentioning the source, because my paths are messed up right now. You can assume that I don't have anything else downloaded or installed other than Django and Python.
This is probably somewhat hacky, but when I want to use the jQueryUI datepicker for a specific form field I do this:
Add the stylesheet in the <head> of my template:
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" />
Add the javascript file at the end of my template:
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
The field of your form with which you want to use the datepicker will have a specific ID. In your case it will probably be id_date_of_birth. So you can select the date of birth textbox by ID and apply the datepicker to it (this assumes you are also using jQuery):
<script>
$(document).ready(function() {
$('#id_date_of_birth').datepicker({firstDay: 1,
dateFormat: "dd/mm/yy",
defaultDate: "16/06/2017",
minDate: "16/06/2017",
maxDate: "25/06/2017"});
});
</script>
Note that this snippet has to come AFTER you include the javascript file. Also, I am setting some defaults you may not need - the simplest way to make it work would be:
<script>
$(document).ready(function() {
$('#id_date_of_birth').datepicker();
});
</script>
Hopefully that helps you out!
I searched and struggled a lot to get the problem fixed
I recommend
this source.
In forms.py:
# Create custom widget in your forms.py file.
class DateInput(forms.DateInput):
input_type = 'date'
In the same forms.py:
# Form class in forms.py
class LastActiveForm(forms.Form):
"""
Last Active Date Form
"""
last_active = forms.DateField(widget=DateInput)
This works perfectly with formset too.
In the template file:
{ form.as_p }
# Only without any external libraries or add-ons
This is what I added to my template and it is working now. To someone in the future looking for an answer, here it is. Although, I must tell you that this might not scale well on large projects, you might have to use this function everywhere or something like that, but for now, this works for me.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Datepicker - Default functionality</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<form action="." method="post">
{% csrf_token %}
{{form.as_p}}
<p>Date: <input type="text" id="datepicker"></p>
<input type="submit" value="Submit" />
</form>
<script>
$( function()
{
$( "#id_date_of_birth" ).datepicker();
$( "#datepicker" ).datepicker();
} );
</script>
</body>
</html>
I recently needed to add a date field with a datepicker to a form. I did this quick so please forgive a typo or 3 :)
The Jquery is referencing an id "#id_date_of_birth", but it would be better practice to make this a class like "datechooser" so you can use it on any form instead of just the "date_of_birth" form field.
Models.py
from django.db import models
class Sample(models.Model):
date_of_birth = models.DateTimeField(help_text='date_of_birth', null=True)
Forms.py
from django.forms import ModelForm, widgets, DateTimeField, DateField, DateInput
class SampleForm(ModelForm):
date_of_birth = DateTimeField(widget = DateInput(format='%Y-%m-%d'),
input_formats=('%Y-%m-%d',),
required=False)
class Meta:
model = Sample
fields = ["date_of_birth",]
Views.py
from django.views import generic
from sample.models import Sample
from sample.forms import SampleForm
def dlp_test(request):
form = SampleForm()
form = SampleForm(initial={'date_of_birth': timezone.now().date()}) # Set an initial value for today
return render(request, 'dlp_test.html', {'form': form})
dlp_test.html
{{ form.date_of_birth }}
{{ form.date_of_birth.errors }}
Datepicker via Jquery for a form field
Header.html
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
$( function() {
$( "#id_date_of_birth" ).datepicker({
dateFormat: 'yy-mm-dd',
changeMonth: true,
changeYear: true
});
});
This is what i do to get datepicker in django forms.
install bootstrap_datepicker_plus by pip command.
pip install django-bootstrap_datepicker_plus
forms.py
from .models import Hello
from django import forms
from bootstrap_datepicker_plus import DatePickerInput
class CreateForm(forms.ModelForm):
class Meta:
model = Hello
fields =[
"Date",
]
widgets = {
'Date': DatePickerInput(),
}
settings.py
INSTALLED_APPS = [
'bootstrap_datepicker_plus',
]

Can I add or update a new variable after render in django template

I've been trying to add or update a variable in the templete before the first render. I have an Ajax request that sends a POST request which works fine, but when I tried to return the new variable, destinations, to the same page/template, index.html, it doesn't appear.
How do I fix this behavior?
view.py
def index(request):
if request.method == 'POST':
dayset = request.POST.get('the_point')
dest = Destination(get_cons(dayset))
destinations = dest.latlond()
context = {'destinations': destinations}
render(request, 'index.html', context)
else:
objan = Antennas(antenas)
antposition = objan.getAntennas()
context = {'antposition': antposition}
return render(request, 'index.html', context)
Temple index.html
<html>
<head>
<meta charset=utf-8 />
<title>DAKARmob</title>
{% load staticfiles %}
<script type="text/javascript" src="{% static "scripts/main.js" %}"></script>
<body>
<script type="text/javascript">
{% for pos in antposition %}
var marker = L.marker([{{pos.1}}, {{pos.2}}], {
icon: L.mapbox.marker.icon({
'marker-color': '#b9e841'
}),
draggable: false
}).on('click', onAnte);
antenas[{{pos.0}}] = [{{pos.1}}, {{pos.2}}];
cluster_ant.addLayer(marker);
{% endfor %}
map.addLayer(cluster_ant);
function onAnte(e) {
var latl = this.getLatLng();
var aux = [latl.lat,latl.lng];
var result = getKeysForValue(antenas, aux);
new_point(result[0]);
function new_point(id) {
console.log(id);
$.ajax({
url : "/", // the endpoint
type : "POST", // http method
data : { the_point : id }, // data sent with the post request
success : function(res) {
console.log("success"); // another sanity check
}
});
}
// OTHER FUNCTIONS FOR THE FUNCTION OF AJAX AND DJANGO
</script>
<div style="position:absolute; top:900px; left:10px; ">
{{ destinations }}
</div>
</body>
</html>
Look at JsonResponse, which you can use to return the new variable as json to your ajax function, which can then be used to set that variable in your template.

Categories

Resources