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

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',
]

Related

Write contents of ace.js editor to file in Django

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.

JSignature Field Not Appearing in Django

First time posting on the site, apologies before hand as I am a newbie.
Building a Django project in Visual Studio for a class and need a signature form to appear on one of the pages. Currently been following this guide: https://pypi.org/project/django-jsignature/ but have hit a roadblock as all I can get to show on the page is a save button. Below I've listed what I've got.
forms.py
from django import forms
...
from jsignature.forms import JSignatureField
from jsignature.widgets import JSignatureWidget
...
class SignatureForm(forms.Form):
signature = JSignatureField()
template.html
{% extends "app/layout.html" %}
{% block content %}
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
{{form.media }}
<form action="." method="POST">
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{% endfor %}
<input type="submit" value="Save"/>
{% csrf_token %}
</form>
</body>
{% endblock %}
views.py
from jsignature.utils import draw_signature
from app.forms import SignatureForm
...
def signature(request):
assert isinstance(request, HttpRequest)
return render(
request,
'app/template.html',
{
'title':'About',
'message':'Your application description page.',
'year':datetime.now().year,
}
)
def my_view(request):
form = SignatureForm(request.POST or None)
if form.is_valid():
signature = form.cleaned_data.get('signature')
if signature:
#as an image
signature_picture = draw_signature(signature)
#or as a file
signature_file_path = draw_signature(signature, as_file=True)
Again, when taken to my template page all that populates is a lone save button. I included this in the body of my layout html page as I had read it could be an issue with running the script on the page but still no luck.
<script src="ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
Can anyone point me in the right direction? Hopefully I have provided sufficient info.
I had the same problem. I fixed it by changing where I put {{ form.media }}.
Documentation says to put it above the form, I instead inserted it bellow all my other JS imports.
base.html
.
.
.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.bundle.min.js"</script>
{% block extra_javascript %}{% endblock %}
form-template.html
{% extends "base.html" %}
{% crispy form main_helper%}
{% block extra_javascript %}
{{form.media}}
{% endblock %}
I know this is old, but I just installed django-jsignature and had the same issue. I am new to Django and would like to share the solution to those that are also new to Django and want to use django-jsignature in their project.
There are a few things you have to check.
First, use Chrome, then go to Developer Tools. Check your console and see if you have Javascript errors. If you do, you have to modify 2 files.
The 2 files you have to modify can be found at https://github.com/fle/django-jsignature/pull/11/commits
Reload your template page, and see if you still have javascript errors on your page.
I am using jQuery Core 3.4.1. and this is working great for me with no errors. I have placed the jquery script link on the head section of my html page.
Remove all other javascript dependencies just to make sure they are not conflicting.
Now if you no longer have javascript errors and you still don't have a signature pad, move to step 2.
Load your html template in Chrome and View Page Source. On where you're supposed to have the signature section, you should see a "hidden" div with in the form. That means that the form loaded correctly in html, but your CSS may cause this section not to display correctly.
If that is the case, try creating a new template and just have the jsignature template code in it without any CSS just to test.
If you do not see a "hidden" div on your signature template html when clicking on View Page Source, that means you're page did not render correctly.
a. On your views.py, make sure you add {'form': form } in your context. This instruction was not included in the Readme.
example: return render(request, 'your_signature_template.html', {'form': form }
b. On your signature_template html file, make sure you have {{ form.media }} on top of your form.
Follow exactly what's in the django jsignature tutorial on the pypi site and just make sure you have the latest version of jquery in the head tag of your template. And also dont forget to pass an empty instance of the Signature form to your render method through to your template
I made a demo. Checkout https://djsign.herokuapp.com
And you can find the codes at https://github.com/mnnlthmpsn/djsignature.git
Same Problem, different solution:
I tried to embed the sign-field in a modal, where AGBs should be shown and signed.
Beforehand i made sure that the signaturefield would show up correctly when using nothing but the example-case by fle plus my own base with header and sidebar. There, everything was working allright.
When trying to embed it into another page (with or without being in a modal), the Signaturefield would not show up, but DevTools (Chrome) showed that it loaded correctly.
I saw the size properties of the field being "ratio" for "height" and "width", and fixed "height" to 200px. Then everything worked all right.
forms.py:
from django import forms
from .models import Signature
from jsignature.widgets import JSignatureWidget
from jsignature.forms import JSignatureField
class SignatureForm(forms.ModelForm):
signature = JSignatureField(widget=JSignatureWidget(jsignature_attrs={'color': '#e0b642', 'height': '200px'}))
class Meta:
model = Signature
fields = ['signature']

Minimal Example for dynamic HTML pages with Django and AJAX

I refer to the following posts:
Reload table data in Django without refreshing the page
Django dynamic HTML table refresh with AJAX
Despite the two post and nice answers, I am still struggling to construct a minimal working example for dynamic HTML pages resorting to Django and AJAX.
I have to following code:
models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^get_more_tables', views.get_more_tables, name='get_more_tables')
]
views.py
from django.shortcuts import render
from .models import Question
def index(request):
a = Question.objects.order_by('-pub_date')
context = {'questions': a}
return render(request, 'polls/index.html', context)
def get_more_tables(request):
a = Question.objects.order_by('-pub_date')
context = {'questions': a}
return render(request, 'polls/get_more_tables.html', context)
index.html
<html>
<body>
<table id="_appendHere">
<tr><td> text </td></tr>
{% for a in questions %}
<tr><td> {{ a.question_text }} </td></tr>
{% endfor %}
</table>
</body>
</html>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
var append_increment = 0;
setInterval(function() {
$.ajax({
type: "GET",
url: "{% url 'get_more_tables' %}",
data: {'append_increment': append_increment}
})
.done(function(response) {
$('#_appendHere').append(response);
append_increment += 10;
});
}, 1000)
get_more_tables.html
{% for a in questions %}
<tr><td> {{ a.question_text }} </td></tr>
{% endfor %}
I have the following issues:
According to Console Error with Ajax: ReferenceError: $ is not defined, I need to set up the js.file in the js-script. If I do not do that, I get the "ReferenceError: $ is not defined" error. Why is that, in particular, as this is not necessary for the previous above mention posts?
If I run http://localhost:8000/polls/, nothing happens. I was assuming that, when I use
q2 = Question(question_text="What's up4?", pub_date=timezone.now())
q2.save()
by python manage.py shell, the entire internal database should be shown. However, nothing is happening. When I refresh the site by hand, all entries are shown.
The inspector console of Mozilla does not show any entry. The network console of Mozilla does show that /pools and the external js file is accessed. However, no continuous access in 1s intervals is shown (not sure if that should be the case).
Your HTML is not valid, for a couple of reasons.
First, you put the script block outside the closing </html> tag. That means it's outside the document itself, and may not be read by the browser.
More importantly, you haven't got your code inside a proper script element. You have an opening tag, but you use that to reference the external jQuery library via the src attribute. You don't have a closing tag at all
You need to put the jQuery reference in its own element, and use proper opening and closing tags for your own script.
<html>
<body>
<table>
...
</table>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
var append_increment = 0;
setInterval(function() {
$.ajax({
type: "GET",
url: "{% url 'get_more_tables' %}",
data: {'append_increment': append_increment}
})
.done(function(response) {
$('#_appendHere').append(response);
append_increment += 10;
});
}, 1000)
</script>
</body>
</html>
You have to externalyze your jquery in another file (without any tags, just the jquery). And add a ready function:
$(document).ready(function(){
// Your JS code here
});
In the html, do as follow:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
<script src="<relative_path_to_your_js>">
The route /polls/ doesn't exist. So nothing happens. You only have routes / and /get_more_tables defined.
I did not understand the last question, what do you enter in the Interactive Console ? (After entering ./manage.py shell)

Column formatters in Flask Admin interface

Hi I have created a Flask admin interface. In one of the field(column), I would like to include a hyperlink.
class workout(db.Model):
equipment = db.Column(db.String(100))
place = db.Column(db.String(100))
image = db.Column(db.Text)
or using Jinja2 macro in template:
I have to create a view which should include the above columns as well as I have to format the image column in the view.
I am really not so sure of how to create the view for the above mentioned custom class model.
from flask_admin.model.template import macro
class WorkoutView(ModelView):
in _macros.html file.
{% macro render_image() %}
Upload images
<script src="https://widget.cloudinary.com/global/all.js" type="text/javascript"></script>
<script type="text/javascript">
document.getElementById("upload_widget_opener").addEventListener("click", function() {
cloudinary.openUploadWidget({ cloud_name: 'mycloudname', sources: [ 'local', 'url', 'camera', 'image_search',
'facebook', 'dropbox', 'google_photos' ], upload_preset: 'myuploadpreset'},
function(error, result) { console.log(error, result) });
}, false);
</script>
{% endmacro %}
IF I run the _macros.html file, it is good and I am getting the hyperlink as expected.
Issue : I am not getting the hyperlink in the column which I formatted when I try to import the macros from _macros.html file
Is there any issue with my syntax in _macros.html or in app.py file ?
I think you are misuse SQLAlchemy and Flask-Admin. CustomModel class inherit from db.Model from SQLAlchemy and CustomModelView class inherit from ModelView from Flask-Admin to control the behavior of that Model in Flask-Admin. You can achieve your purpose as follows:
Use form_widget_args to add id attribute to form field;
Inherit create.html & edit.html to add javascript.
class ExampleModelView(ModelView):
# ...
edit_template = "admin/edit.html"
create_template = "admin/create.html"
form_widget_args = {
"image": {
"id": "cloudinary"
}
}
# ...
# template inherit. "edit.html" is same as "create.html" except the first line.
{% extends "admin/model/create.html" %}
{% block tail %}
{{ super() }}
<script src="https://widget.cloudinary.com/global/all.js" type="text/javascript"></script>
<script type="text/javascript">
# js code to upload image and return response
</script>
{% endblock %}

How to autocomplete a search form?

I have a search form and it works fine. Now I would like my search form autocomplete.I tried using django autocomplete light but I have a problem implementing it.
Is it possible to use my existing code, add JavaScript and make it work?
I tried to do it myself but I came to a wall.
I would really appreciate if someone could help me with this, give me a hint or a link for a working demo or tutorial.
This is my current code. Thanks for your time.
views.py
def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
search_list = Book.objects.filter(
Q(title__icontains=q) | Q(description__icontains=q))
return render_to_response('books/search_results.html', {'search_list': search_list, 'query': q}, context_instance=RequestContext(request))
else:
return render_to_response('books/please_submit.html', {}, context_instance=RequestContext(request))
urls.py
urlpatterns = patterns('',
url(r'^search/$','papers.views.search', name='search'),
)
search.html
<form method='get' action='/search/'>
<input type='text' name='q' class="btn btn-theme btn-sm btn-min-block biggerForm">
<input type='submit' value='Search' class="btn btn-theme btn-sm btn-min-block">
</form>
Django-autocomplete-light is tricky to set up and in my opinion its easier using other autocompletes.
Here is how I got it working using bootstrap 2. (There is a bootstrap 3 compatible library as well, and the configuration is more or less the same https://github.com/bassjobsen/Bootstrap-3-Typeahead).
You need a few things to work together.
1: Create a view that will process the autocomplete request and return suggestions.
so in views.py
def book_autocomplete(request, **kwargs):
term = request.GET.__getitem__('query')
books = [str(book) for book in book.objects.filter(Q(title__icontains=q) | Q(description__icontains=q))]
return HttpResponse(json.dumps(books))
And in urls.py add an entry:
url(r'^autocomplete/book_autocomplete/' , booking.ebsadmin.book_autocomplete , name='book_autocomplete'),
2: Load the bootstrap typeahead/autocomplete code into your page. The project I inherited was already using bootstrap 2, so this code was already there.
So in your template in the head section (this will probably differ depending on the the directory structure of your static files):
<script type="text/javascript" src="{{ STATIC_URL }}bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}bootstrap/css/bootstrap.min.css" />
3: Connect the bootstrap typeahead/autcomplete to your view.
I created a file book_autocomplete.js, and added it to my static files folder. This tells it to attach the autocomplete to the element with id book-search (you will have to give the search box on your form and id equivalent to the '#book-search' that I have used here. An example on how to do this in your form definition https://stackoverflow.com/a/5827671/686016):
book_search_typeahead.js
$(document).ready(function() {
$('#book-search').typeahead({source: function (query, process) {
return $.getJSON(
'/autocomplete/book_autocomplete/', // this is the url for the view we created in step 1
{ query : query },
function (data) {
console.log(data) ;
return process(data);
});
}});
});
back to your template and add this line to load the javascript that we just created:
<script type='text/javascript' src='{{ STATIC_URL }}book_search_typeahead.js' ></script>
I think that is everything.
#wobbily_col answer works obviously but generally you want to avoid hitting a relational database to create autocomplete results. I have made an autocomplete library that works fast and is easy to use. But all it does is to give you text results back. It is up to you to feed it data and make its responses in your API. Checkout: https://github.com/wearefair/fast-autocomplete
And here is an explanation of how it works: http://zepworks.com/posts/you-autocomplete-me/

Categories

Resources