Add full example of front-office usage
This commit is contained in:
103
README.rst
103
README.rst
@@ -22,17 +22,15 @@ It provides:
|
|||||||
.. image:: https://github.com/fle/django-jsignature/blob/master/screen.png
|
.. image:: https://github.com/fle/django-jsignature/blob/master/screen.png
|
||||||
|
|
||||||
==================
|
==================
|
||||||
INSTALL
|
Installation
|
||||||
==================
|
==================
|
||||||
|
|
||||||
For now:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pip install django-jsignature
|
pip install django-jsignature
|
||||||
|
|
||||||
==================
|
==================
|
||||||
USAGE
|
Usage
|
||||||
==================
|
==================
|
||||||
|
|
||||||
* Add ``jsignature`` to your ``INSTALLED_APPS``:
|
* Add ``jsignature`` to your ``INSTALLED_APPS``:
|
||||||
@@ -45,48 +43,37 @@ USAGE
|
|||||||
'jsignature',
|
'jsignature',
|
||||||
)
|
)
|
||||||
|
|
||||||
* Use provided form field and widget:
|
* Use provided model field (for easy storage):
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# forms.py
|
# models.py
|
||||||
from django import forms
|
from django.db import models
|
||||||
from jsignature.forms import JSignatureField
|
from jsignature.fields import JSignatureField
|
||||||
|
|
||||||
class SignatureForm(forms.Form):
|
class SignatureModel(models.Model):
|
||||||
signature = JSignatureField()
|
signature = JSignatureField()
|
||||||
|
|
||||||
* In your template
|
* In your form template
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
{{ form.media }}
|
{{ form.media }}
|
||||||
<form action="." method="POST">
|
<form action="" method="post">
|
||||||
{% for field in form %}
|
{{ form }}
|
||||||
{{ field.label_tag }}
|
<input type="submit" value="Save" />
|
||||||
{{ field }}
|
|
||||||
{% endfor %}
|
|
||||||
<input type="submit" value="Save"/>
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
* Render image after form validation:
|
* Render image from db value in your display template:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# views.py
|
{# yourtemplate.html #}
|
||||||
from jsignature.utils import draw_signature
|
{% load jsignature_filters %}
|
||||||
from myapp.forms import SignatureForm
|
|
||||||
|
<img src="{{ obj.signature|signature_base64 }}" alt="{{ obj }}" />
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
* By default, jSignature is made to work outside of admin, requiring that
|
* By default, jSignature is made to work outside of admin, requiring that
|
||||||
you include the jQuery library in your ``<head>``.
|
you include the jQuery library in your ``<head>``.
|
||||||
@@ -95,8 +82,11 @@ USAGE
|
|||||||
``JSIGNATURE_JQUERY`` setting to ``admin``. Otherwise if set to any url
|
``JSIGNATURE_JQUERY`` setting to ``admin``. Otherwise if set to any url
|
||||||
pointing to jQuery, it will be automatically included.
|
pointing to jQuery, it will be automatically included.
|
||||||
|
|
||||||
|
It is strongly suggested to take example from ``example_project``, which is
|
||||||
|
`located in this repo <https://github.com/fle/django-jsignature/tree/master/example_project>`_
|
||||||
|
|
||||||
==================
|
==================
|
||||||
CUSTOMIZATION
|
Customization
|
||||||
==================
|
==================
|
||||||
|
|
||||||
JSignature plugin options are available in python:
|
JSignature plugin options are available in python:
|
||||||
@@ -131,10 +121,11 @@ Available settings are:
|
|||||||
* ``JSIGNATURE_RESET_BUTTON`` (ResetButton)
|
* ``JSIGNATURE_RESET_BUTTON`` (ResetButton)
|
||||||
|
|
||||||
==================
|
==================
|
||||||
IN YOUR MODELS
|
In your models
|
||||||
==================
|
==================
|
||||||
|
|
||||||
If you want to store signatures, provided mixin gives a ``signature`` and a ``signature_date`` that update themselves:
|
If you want to store signatures easily, a provided mixin gives a ``signature``
|
||||||
|
and a ``signature_date`` that update themselves:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@@ -145,6 +136,41 @@ If you want to store signatures, provided mixin gives a ``signature`` and a ``si
|
|||||||
name = models.CharField()
|
name = models.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
In your forms
|
||||||
|
==================
|
||||||
|
|
||||||
|
* If you need more precise handling of the form field, you can use it directly:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# forms.py
|
||||||
|
from django import forms
|
||||||
|
from jsignature.forms import JSignatureField
|
||||||
|
|
||||||
|
class SignatureForm(forms.Form):
|
||||||
|
signature = JSignatureField()
|
||||||
|
|
||||||
|
|
||||||
|
* And upon saving, have direct access to the image with ``draw_signature()``
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# views.py
|
||||||
|
from jsignature.utils import draw_signature
|
||||||
|
from myapp.forms import SignatureForm
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Example project
|
Example project
|
||||||
==================
|
==================
|
||||||
@@ -163,16 +189,17 @@ If you want to have a demo of this package, just use the example project:
|
|||||||
./manage.py migrate
|
./manage.py migrate
|
||||||
./manage.py createsuperuser
|
./manage.py createsuperuser
|
||||||
|
|
||||||
Fill the user info, launch django with ``./manage.py runserver`` and head over to
|
Fill the user info, launch django with ``./manage.py runserver`` and head over
|
||||||
`http://127.0.0.1:8000/ <http://127.0.0.1:8000/>`_ and login with the
|
to `http://127.0.0.1:8000/ <http://127.0.0.1:8000/>`_, you can also
|
||||||
credentials your provided.
|
`login to the admin <http://127.0.0.1:8000/admin>`_ with the credentials your
|
||||||
|
provided.
|
||||||
|
|
||||||
==================
|
==================
|
||||||
AUTHORS
|
Authors
|
||||||
==================
|
==================
|
||||||
|
|
||||||
* Florent Lebreton <florent.lebreton@makina-corpus.com>
|
* Florent Lebreton <florent.lebreton@makina-corpus.com> (original author)
|
||||||
* Sébastien Corbin <sebastien.corbin@makina-corpus.com>
|
* Sébastien Corbin <sebastien.corbin@makina-corpus.com> (maintainer)
|
||||||
|
|
||||||
|makinacom|_
|
|makinacom|_
|
||||||
|
|
||||||
|
|||||||
39
example_project/templates/base.html
Normal file
39
example_project/templates/base.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<title>Example project</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'admin:index' %}">Admnistration</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'list' %}">List</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'create' %}">Create</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||||
|
{% block extra_media %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block extra_media %}
|
||||||
|
{{ form.media }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="" method="post">
|
||||||
|
{{ form }}
|
||||||
|
<input type="submit" value="Save" class="btn btn-success" />
|
||||||
|
<a href="{% url 'list' %}" class="btn btn-danger">Cancel</a>
|
||||||
|
{% csrf_token %}
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{% extends "base.html" %}{% load jsignature_filters %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>List</h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for obj in object_list %}
|
||||||
|
<li>
|
||||||
|
<dl>
|
||||||
|
<dt>Raw data (from db)</dt>
|
||||||
|
<dd>{{ obj.signature }}</dd>
|
||||||
|
<dt>As image</dt>
|
||||||
|
<dd>
|
||||||
|
<img src="{{ obj.signature|signature_base64 }}" alt="{{ obj }}" />
|
||||||
|
<a href="{% url 'update' obj.pk %}" class="btn btn-primary">
|
||||||
|
Update
|
||||||
|
</a>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<a href="{% url 'create' %}" class="btn btn-primary">Create</a>
|
||||||
|
{% endblock %}
|
||||||
@@ -3,6 +3,11 @@ from __future__ import unicode_literals
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
|
from example_project import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', admin.site.urls),
|
path('', views.ExampleListView.as_view(), name='list'),
|
||||||
|
path('create', views.ExampleCreateView.as_view(), name='create'),
|
||||||
|
path('update/<int:pk>', views.ExampleUpdateView.as_view(), name='update'),
|
||||||
|
path('admin', admin.site.urls),
|
||||||
]
|
]
|
||||||
|
|||||||
20
example_project/views.py
Normal file
20
example_project/views.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.views import generic
|
||||||
|
|
||||||
|
from example_project.models import ExampleModel
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleCreateView(generic.CreateView):
|
||||||
|
model = ExampleModel
|
||||||
|
fields = '__all__'
|
||||||
|
success_url = reverse_lazy('list')
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleUpdateView(generic.UpdateView):
|
||||||
|
model = ExampleModel
|
||||||
|
fields = '__all__'
|
||||||
|
success_url = reverse_lazy('list')
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleListView(generic.ListView):
|
||||||
|
model = ExampleModel
|
||||||
Reference in New Issue
Block a user