django-floppyforms-1.6.0/000077500000000000000000000000001263013462600153415ustar00rootroot00000000000000django-floppyforms-1.6.0/.gitignore000066400000000000000000000001251263013462600173270ustar00rootroot00000000000000django_floppyforms.egg-info dist build docs/_build .coverage .tox/ *.pyc __pycache__ django-floppyforms-1.6.0/.travis.yml000066400000000000000000000025551263013462600174610ustar00rootroot00000000000000language: python python: 2.7 env: - TOXENV=py26-14 - TOXENV=py26-15 - TOXENV=py26-16 - TOXENV=py27-14 - TOXENV=py27-15 - TOXENV=py27-16 - TOXENV=py27-17 - TOXENV=py27-18 - TOXENV=py27-19 - TOXENV=py32-15 - TOXENV=py32-16 - TOXENV=py32-17 - TOXENV=py32-18 - TOXENV=py32-18 - TOXENV=py33-15 - TOXENV=py33-16 - TOXENV=py33-17 - TOXENV=py33-18 - TOXENV=py34-15 - TOXENV=py34-16 - TOXENV=py34-17 - TOXENV=py34-18 - TOXENV=py34-19 - TOXENV=pypy-14 - TOXENV=pypy-15 - TOXENV=pypy-16 - TOXENV=pypy-17 - TOXENV=pypy-18 - TOXENV=pypy-19 - TOXENV=docs - TOXENV=flake8 before_install: - sudo apt-get -q -y update # The following three lines is a fix for travis CI, since it wouldn't be # able to install the dependencies correctly. # See: https://github.com/travis-ci/travis-ci/issues/2683 - sudo mv /etc/apt/sources.list.d/pgdg-source.list* /tmp - sudo apt-get remove -q -y binutils gdal-bin libproj-dev libgeos-c1 - sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable # Required to install Pillow - sudo apt-get -q -y install build-essential # GIS requirements. - sudo apt-get -q -y install binutils gdal-bin libproj-dev libgeos-c1 install: - pip install tox script: - tox notifications: irc: channels: - "irc.freenode.org#django-floppyforms" on_success: change on_failure: always django-floppyforms-1.6.0/CHANGES.rst000066400000000000000000000162611263013462600171510ustar00rootroot00000000000000Changelog --------- 1.6.0 ~~~~~ * `#160`_: Django 1.9 support! Thanks to Jonas Haag for the patch. .. _#160: https://github.com/gregmuellegger/django-floppyforms/pull/160 1.5.2 ~~~~~ * `#156`_: The ``min``, ``max``, ``step`` attributes for ``DecimalField`` and ``FloatField`` were localized which can result in invalid values (rendering ``0.01`` as ``0,01`` in respective locales). Those attributes won't get localized anymore. Thanks to Yannick Chabbert for the fix. .. _#156: https://github.com/gregmuellegger/django-floppyforms/pull/156 1.5.1 ~~~~~ * `FloatField`` now fills in ``min``, ``max``, and ``step`` attributes to match the behaviour of `DecimalField`. Leaving out the ``step`` attribute would result in widgets that only allow integers to be filled in (HTML 5 default for ``step`` is ``1``). 1.5.0 ~~~~~ * `#148`_: Added support for custom ``label_suffix`` arguments in forms and fields. * The contents in ``floppyforms/input.html`` is now wrapped in a ``{% block content %}`` for easier extending. * `#70`_: `DecimalField`` now fills in ``min``, ``max``, and ``step`` attributes for better client side validation. Use the ``novalidate`` attribute on your ``
`` tag to disable HTML5 input validation in the browser. Thanks to caacree for the patch. .. _#148: https://github.com/gregmuellegger/django-floppyforms/issues/148 .. _#70: https://github.com/gregmuellegger/django-floppyforms/issues/70 1.4.1 ~~~~~ * Fixed source distribution to include all files in ``floppyforms/static/floppyforms/openlayers``. 1.4.0 ~~~~~ * Every widget is now using its own template. Previously all widgets that are based on the HTML ```` tag used the generic ``floppyforms/input.html`` template. Now the widgets each have a custom element for easier customisation. For example ``CheckboxInput`` now uses ``floppyforms/checkbox.html`` instead of ``floppyforms/input.html``. See `Widgets reference `_ for a complete list of available widgets and which templates they use. * Adjusting the SRIDs used in the GeoDjango widgets to conform with Django 1.7. Thanks to Tyler Tipton for the patch. * Python 3.2 is now officially supported. * Django 1.8 is now officially supported. django-floppyforms no longers triggers Django deprecation warnings. * Adding `OpenLayers`_ distribution to django-floppyforms static files in order to better support HTTPS setups when GIS widgets are used (See #15 for more details). * Fix: ``python setup.py bdist_rpm`` failed because of wrong string encodings in setup.py. Thanks to Yuki Izumi for the fix. * Fix: The ``CheckboxInput`` widget did detect different values in Python 2 when given ``'False'`` and ``u'False'`` as data. Thanks to @artscoop for the patch. * Fix: ``MultipleChoiceField`` can now correctly be rendered as hidden field by using the ``as_hidden`` helper in the template. That was not working previously as there was no value set for ``MultipleChoiceField.hidden_widget``. .. _OpenLayers: http://openlayers.org/ 1.3.0 ~~~~~ * DateInput widget renders hardcoded "%Y-%m-%d" format. We don't allow custom formats there since the "%Y-%m-%d" format is what browsers are submitting with HTML5 date input fields. Thanks to Bojan Mihelac for the patch. * Adding ``supports_microseconds`` attribute to all relevant widget classes. Thanks to Stephen Burrows for the patch. * Using a property for ``Widget.is_hidden`` attribute on widgets to be in conformance with Django 1.7 default widget implementation. * The docs mentioned that the current ``ModelForm`` behaviour in ``floppyforms.__future__`` will become the default in 1.3. This is postpone for one release and will be part of 1.4. 1.2.0 ~~~~~ * Subclasses of ``floppyforms.models.ModelForm`` did not convert widgets of form fields that were automatically created for the existing model fields into the floppyform variants. This is now changed, thanks to a patch by Stephen Burrows. Previously you had to set the widgets your self in a model form. For example you would write:: import floppyforms as forms class ProfileForm(forms.ModelForm): class Meta: model = Profile widgets = { 'name': forms.TextInput, 'url': forms.URLInput, ... } Now this is done automatically. But since this is a kind-of backwardsincompatible change, you need to use a special import:: import floppyforms.__future__ as forms class ProfileForm(forms.ModelForm): class Meta: model = Profile This feature will become the default behaviour in floppyforms 2.0. See the documentation for more information: http://django-floppyforms.readthedocs.org/en/latest/usage.html#modelforms * If you added an attribute with value 1 to the attrs kwargs (e.g. ``{'value': 1}``, you would get no attribute value in the rendered html (e.g. ``value`` instead of ``value="1"``). That's fixed now, thanks to Viktor Ershov for the report. * All floppyform widget classes now take a ``template_name`` argument in the ``__init__`` and ``render`` method. Thanks to Carl Meyer for the patch. 1.1.1 ~~~~~ * Fix for Django 1.6 * Fix for GIS widgets on Django 1.4 and some versions of GEOS. 1.1 ~~~ * Added GenericIPAddressField. * Django 1.5 and Python 3.3 support added. * Django 1.3 support dropped. * GIS widgets switched to stable OpenLayers release instead of a dev build. * Fixed ``Textarea`` widget template to work with a non-empty ``TEMPLATE_STRING_IF_INVALID`` setting. Thanks to Leon Matthews for the report. * Fixed context handling in widget rendering. It didn't take care of popping the context as often as it was pushed onto. This could cause strange behaviour in the template by leaking variables into outer scopes. Thanks to David Danier for the report. * Added missing empty choice for selectboxes in ``SelectDateWidget``. Thanks fsx999 for the report. * ``IntegerField`` now automatically passes its ``min_value`` and ``max_value`` (if provided) to the ``NumberInput`` widget. * Added basic support for ```` elements for suggestions in ``Input`` widgets. * ``date``, ``datetime`` and ``time`` inputs are not localized anymore. The HTML5 spec requires the rendered values to be RFC3339-compliant and the browsers are in charge of localization. If you still want localized date/time inputs, use those provided by Django or override the ``_format_value()`` method of the relevant widgets. 1.0 ~~~ * cleaned up the behaviour of ``attrs`` * compatible with Django 1.3 and 1.4 * ```` support in select widgets * ``Select`` widgets: renamed ``choices`` context variable to ``optgroups``. This is **backwards-incompatible**: if you have custom templates for ``Select`` widgets, they need to be updated. * ``get_context()`` is more reliable * Added ``form``, ``formrow``, ``formfield``, ``formconfig`` and ``widget`` template tags. * Added template-based form layout system. * Added ability to render widgets with the broader page context, for instance for django-sekizai compatibility. 0.4 ~~~ * All widgets from Django have their floppyforms equivalent * Added widgets for GeoDjango django-floppyforms-1.6.0/LICENSE000066400000000000000000000060751263013462600163560ustar00rootroot00000000000000Copyright (c) 2009-2012, Bruno Renié All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of django-floppyforms nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. For the base test cases (providing assertHTMLEquals and assertTemplatesUsed): Copyright (c) Django Software Foundation and individual contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Django nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. django-floppyforms-1.6.0/MANIFEST.in000066400000000000000000000005241263013462600171000ustar00rootroot00000000000000include README.rst include CHANGES.rst recursive-include floppyforms/templates * recursive-include floppyforms/static * recursive-include requirements *.txt recursive-include docs *.rst *.png recursive-include tests *.py *.html recursive-include tests/demo/templates * recursive-include tests/templates * include docs/Makefile docs/conf.py django-floppyforms-1.6.0/README.rst000066400000000000000000000041011263013462600170240ustar00rootroot00000000000000django-floppyforms ================== .. image:: https://api.travis-ci.org/gregmuellegger/django-floppyforms.png :alt: Build Status :target: https://travis-ci.org/gregmuellegger/django-floppyforms Full control of form rendering in the templates. * Authors: Gregor Müllegger and many many `contributors`_ * Original creator: Bruno Renié started this project and kept it going for many years. * Licence: BSD * Requirements: homework -- read `this`_. .. _contributors: https://github.com/gregmuellegger/django-floppyforms/contributors .. _this: http://diveintohtml5.info/forms.html Installation ------------ * ``pip install -U django-floppyforms`` * Add ``floppyforms`` to your ``INSTALLED_APPS`` For extensive documentation see the ``docs`` folder or `read it on readthedocs`_ .. _read it on readthedocs: http://django-floppyforms.readthedocs.org/ To install the `in-development version`_ of django-floppyforms, run ``pip install "https://github.com/gregmuellegger/django-floppyforms/tarball/master#egg=django-floppyforms"``. .. _in-development version: https://github.com/gregmuellegger/django-floppyforms Help ---- Create a ticket in the `issues section on github`_ or ask your questions on the #django-floppyforms IRC channel on freenode. You can get professional consulting regarding django-floppyforms or any other Django related work from django-floppyforms' maintainer `Gregor Müllegger`_. .. _issues section on github: https://github.com/gregmuellegger/django-floppyforms/issues .. _Gregor Müllegger: http://gremu.net/ Bugs ---- Really? Oh well... Please Report. Or better, fix :) We are happy to help you through the process of fixing and testing a bug. Just get in touch. Development ----------- Thanks for asking! Get the code:: git clone git@github.com:gregmuellegger/django-floppyforms.git cd django-floppyforms virtualenv -p python2 env source env/bin/activate add2virtualenv . Install the development requirements:: pip install "tox>=1.8" Run the tests:: tox -e py27-16 You can see all the supported test configurations with ``tox -l``. django-floppyforms-1.6.0/benchmark.py000066400000000000000000000023271263013462600176510ustar00rootroot00000000000000""" Compares the rendering speed between Django forms and django-floppyforms Usage: DJANGO_SETTINGS_MODULE=benchmark python benchmark.py [--cache] """ import sys import timeit django = """from django import forms class DjangoForm(forms.Form): text = forms.CharField() slug = forms.SlugField() some_bool = forms.BooleanField() email = forms.EmailField() date = forms.DateTimeField() file_ = forms.FileField() rendered = DjangoForm().as_p()""" flop = """import floppyforms as forms class FloppyForm(forms.Form): text = forms.CharField() slug = forms.SlugField() some_bool = forms.BooleanField() email = forms.EmailField() date = forms.DateTimeField() file_ = forms.FileField() rendered = FloppyForm().as_p()""" def time(stmt): t = timeit.Timer(stmt=stmt) return t.timeit(number=1000) if __name__ == '__main__': print "Plain Django:", time(django) print "django-floppyforms:", time(flop) INSTALLED_APPS = ( 'floppyforms' ) if '--cache' in sys.argv: TEMPLATE_LOADERS = ( ('django.template.loaders.cached.Loader', ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', )), ) django-floppyforms-1.6.0/docs/000077500000000000000000000000001263013462600162715ustar00rootroot00000000000000django-floppyforms-1.6.0/docs/Makefile000066400000000000000000000110361263013462600177320ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-floppyforms.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-floppyforms.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/django-floppyforms" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-floppyforms" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." django-floppyforms-1.6.0/docs/bootstrap.rst000066400000000000000000000065431263013462600210500ustar00rootroot00000000000000Layout example with Bootstrap ============================= If you use Floppyforms with Bootstrap you might be interested in using a bootstrap layout for your form. What you have to do is to create those two templates: **floppyforms/templates/floppyforms/layouts/bootstrap.html**: .. code-block:: django {% load floppyforms %}{% block formconfig %}{% formconfig row using "floppyforms/rows/bootstrap.html" %}{% endblock %} {% block forms %}{% for form in forms %} {% block errors %} {% for error in form.non_field_errors %}
× {{ error }}
{% endfor %} {% for error in form|hidden_field_errors %}
× {{ error }}
{% endfor %} {% endblock errors %} {% block rows %} {% for field in form.visible_fields %} {% if forloop.last %}{% formconfig row with hidden_fields=form.hidden_fields %}{% endif %} {% block row %}{% formrow field %}{% endblock %} {% endfor %} {% if not form.visible_fields %}{% for field in form.hidden_fields %}{% formfield field %}{% endfor %}{% endif %} {% endblock %} {% endfor %}{% endblock %} **floppyforms/templates/floppyforms/rows/bootstrap.html**: .. code-block:: django {% load floppyforms %}{% block row %}{% for field in fields %}
{% with classes=field.css_classes label=label|default:field.label help_text=help_text|default:field.help_text %} {% block label %}{% if field|id %}{% endif %}{% endblock %} {% block field %}
{% block widget %}{% formfield field %}{% endblock %} {% block errors %}{% include "floppyforms/errors.html" with errors=field.errors %}{% endblock %} {% block help_text %}{% if field.help_text %}

{{ field.help_text }}

{% endif %}{% endblock %} {% block hidden_fields %}{% for field in hidden_fields %}{{ field.as_hidden }}{% endfor %}{% endblock %}
{% endblock %} {% endwith %}
{% endfor %}{% endblock %} You can also define this layout by default: **floppyforms/templates/floppyforms/layouts/default.html**: .. code-block:: django {% extends "floppyforms/layouts/bootstrap.html" %} You can also make a change to the error display: **floppyforms/templates/floppyforms/errors.html**: .. code-block:: django {% if errors %}{% for error in errors %}{{ error }}{% if not forloop.last %}
{% endif %}{% endfor %}
{% endif %} And that's it, you now have a perfect display for your form with bootstrap. django-floppyforms-1.6.0/docs/changelog.rst000066400000000000000000000000341263013462600207470ustar00rootroot00000000000000.. include:: ../CHANGES.rst django-floppyforms-1.6.0/docs/conf.py000066400000000000000000000162261263013462600175770ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # django-floppyforms documentation build configuration file, created by # sphinx-quickstart on Fri Nov 26 16:01:17 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import datetime # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'django-floppyforms' copyright = u'2010-{0}, Bruno Renié and contributors'.format( datetime.datetime.today().year) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # try: from floppyforms import __version__ # The short X.Y version. version = '.'.join(__version__.split('.')[:2]) # The full version, including alpha/beta/rc tags. release = __version__ except ImportError: version = release = 'dev' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. #html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". #html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'django-floppyformsdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'django-floppyforms.tex', u'django-floppyforms Documentation', u'Bruno Renié', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'django-floppyforms', u'django-floppyforms Documentation', [u'Bruno Renié'], 1) ] # gorun DIRECTORIES = ( ('', 'make html'), ) django-floppyforms-1.6.0/docs/customization.rst000066400000000000000000000075271263013462600217460ustar00rootroot00000000000000Customization ============= Override default templates -------------------------- Widgets have a ``template_name`` attribute that points to the template that is used when rendering the form. Default templates are provided for all :doc:`built-in widgets `. In most cases the default implementation of these templates have no specific behaviour and simply inherit from ``floppyforms/input.html``. They are provided mainly to give an easy way for a site-wide customization of how a specifig widget is rendered. You can easily override these templates in your project-level ``TEMPLATE_DIRS``, assuming they take precedence over app-level templates. Custom widgets with custom templates ------------------------------------ If you want to override the rendering behaviour only for a few widgets, you can extend a ``Widget`` class from FloppyForms and override the ``template_name`` attribute:: import floppyforms as forms class OtherEmailInput(forms.EmailInput): template_name = 'path/to/other_email.html' Then, the output can be customized in ``other_email.html``: .. code-block:: jinja Here we have a hardcoded placeholder without needing to instantiate the widget with an ``attrs`` dictionary:: class EmailForm(forms.Form): email = forms.EmailField(widget=OtherEmailInput()) .. _template_name_customization: You can also customize the ``template_name`` without subclassing, by passing it as an argument when instantiating the widget:: class EmailForm(forms.Form): email = forms.EmailField( widget=forms.EmailInput(template_name='path/to/other_email.html')) For advanced use, you can even customize the template used per-render, by passing a ``template_name`` argument to the widget's ``render()`` method. Adding more template variables ------------------------------ There is also a way to add extra context. This is done by subclassing the widget class and extending the ``get_context()`` method:: class OtherEmailInput(forms.EmailInput): template_name = 'path/to/other.html' def get_context(self, name, value, attrs): ctx = super(OtherEmailInput, self).get_context(name, value, attrs) ctx['foo'] = 'bar' return ctx And then the ``other.html`` template can make use of the ``{{ foo }}`` context variable. ``get_context()`` takes ``name``, ``value`` and ``attrs`` as arguments, except for all ``Select`` widgets which take an additional ``choices`` argument. In case you don't need the arguments passed to ``get_context()``, you can extend ``get_context_data()`` which doesn't take any arguments:: class EmailInput(forms.EmailInput): def get_context_data(self): ctx = super(EmailInput, self).get_context_data() ctx.update({ 'placeholder': 'hello@example.com', }) return ctx Altering the widget's ``attrs`` ------------------------------- All widget attibutes except for ``type``, ``name``, ``value`` and ``required`` are put in the ``attrs`` context variable, which you can extend in ``get_context()``: .. code-block:: python def get_context(self, name, value, attrs): ctx = super(MyWidget, self).get_context(name, value, attrs) ctx['attrs']['class'] = 'mywidget' return ctx This will render the widget with an additional ``class="mywidget"`` attribute. If you want only the attribute's key to be rendered, set it to ``True``: .. code-block:: python def get_context(self, name, value, attrs): ctx = super(MyWidget, self).get_context(name, value, attrs) ctx['attrs']['awesome'] = True return ctx This will simply add ``awesome`` as a key-only attribute. django-floppyforms-1.6.0/docs/differences.rst000066400000000000000000000157551263013462600213150ustar00rootroot00000000000000Differences with django.forms ============================= So, you have a project already using ``django.forms``, and you're considering a switch to floppyforms? Here's what you need to know, assuming the only change you've made to your code is a simple change, from: .. code-block:: python from django import forms to: .. code-block:: python import floppyforms as forms .. note:: ``django.forms.*`` modules Other modules contained by ``django.forms``, such as ``forms``, ``utils`` and ``formsets`` have not been aliased. HTML 5 forms! ------------- Floppyforms adds a couple of HTML 5 features on top of the standard Django widgets: HTML syntax, more native widget types, the ``required`` attribute and client-side validation. HTML syntax instead of XHTML ```````````````````````````` Floppyforms uses an HTML syntax instead of Django's XHTML syntax. You will see ```` and not ````. Native widget types ``````````````````` Floppyforms tries to use the native HTML5 widgets whenever it's possible. Thus some widgets which used to be simple ``TextInputs`` in ``django.forms`` are now specific input that will render as ```` with the HTML5 types such as ``url``, ``email``. See :ref:`widgets` for a detailed list of specific widgets. For instance, if you have declared a form using django.forms: .. code-block:: python class ThisForm(forms.Form): date = forms.DateField() The ``date`` field will be rendered as an ````. However, by just changing the forms library to floppyforms, the input will be an ````. Required attribute `````````````````` In addition to the various input types, every required field has the ``required`` attribute set to ``True`` on its widget. That means that every ```` widget for a required field will be rendered as ````. This is used for client-side validation: for instance, Firefox 4 won't let the user submit the form unless he's filled the input. This saves HTTP requests but doesn't mean you can stop validating user input. Client-side validation `````````````````````` Like with the ``required`` attribute, the ``pattern`` attribute is especially interesting for slightly more complex client-side validation. The ``SlugField`` and the ``IPAddressField`` both have a pattern attached to the ````. However having these validations backed directly into the HTML and therefore allowing the browser to validate the user input might not always what you want to have. Sometimes you just want to have a form where it should be allowed to submit invalid data. In that case you can use the ``novalidate`` attribute on the ```` HTML tag or the ``formnovalidate`` attribute on the submit button: .. code-block:: html This input will not be validated:
Another way to not validate the form in the browser is using the formnovalidate attribute on the submit button:
Read the corresponding documentation for `novalidate`_ and `formnovalidate`_ on the Mozilla Developer Network if you want to know more. .. _novalidate: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-novalidate .. _formnovalidate: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-formnovalidate ModelForms ---------- Prior to version 1.2 of django-floppyforms, you had to take some manual efforts to make your modelforms work with floppyforms. This is now done seemlesly, but since this was introduced a backwards incompatible change, it was necessary to provde a deprecation path. So if you start out new with django-floppyforms just use ``import floppyforms.__future__ as forms`` as your import instead of ``import floppyforms as forms`` when you want to define modelforms. For more information see the :ref:`section about modelforms in the usage documentation `. ``help_text`` values are autoescaped by default ----------------------------------------------- If you use HTML in the ``help_text`` value for a Django form field and are not using django-floppyforms, then you will get the correct HTML rendered in the template. For example you have this form:: from django import forms class DjangoForm(forms.Form): myfield = forms.CharField(help_text='A help text.') When you now use this form with ``{{ form.as_p }}`` in the template, you will get the help text put in the template as it is, with no HTML escaping. That might imply a security risk if your help text contains content from untrusted sources. django-floppyforms applies autoescaping by default to the help text. So if you define:: import floppyforms as forms class FloppyForm(forms.Form): myfield = forms.CharField(help_text='A help text.') And then use ``{{ form.as_p }}``, you will get an output that contains ``A <strong&;gt;help</strong> text.``. You can disable the autoescaping of the help text by using Django's ``mark_safe`` helper:: from django.utils.html import mark_safe import floppyforms as forms class FloppyForm(forms.Form): myfield = forms.CharField(help_text=mark_safe('A help text.')) ``TEMPLATE_STRING_IF_INVALID`` caveats -------------------------------------- The use of a non-empty ``TEMPLATE_STRING_IF_INVALID`` setting can impact rendering. Missing template variables are rendered using the content of ``TEMPLATE_STRING_IF_INVALID`` but filters used on non-existing variables are not applied (see `django's documentation on how invalid template variables are handled`__ for more details). __ https://docs.djangoproject.com/en/dev/ref/templates/api/#invalid-template-variables django-floppyforms assumes in its predefined form layouts that all filters are applied. You can work around this by making your ``TEMPLATE_STRING_IF_INVALID`` evaluate to ``False`` but still keep its string representation. Here is an example how you could achieve this in your ``settings.py``: .. code-block:: python # on Python 2 class InvalidVariable(unicode): def __nonzero__(self): return False # on Python 3 class InvalidVariable(str): def __bool__(self): return False TEMPLATE_STRING_IF_INVALID = InvalidVariable(u'INVALID') Getting back Django's behaviour ------------------------------- If you need to get the same output as standard Django forms: * Override ``floppyforms/input.html``, ``floppyforms/radio.html``, ``floppyforms/clearable_input.html``, ``floppyforms/textarea.html`` and ``floppyforms/checkbox_select.html`` to use an XHTML syntax * Remove the ``required`` attribute from the templates as well * Make sure your fields which have HTML5 widgets by default get simple ``TextInputs`` instead: .. code-block:: python class Foo(forms.Form): url = forms.URLField(widget=forms.TextInput) django-floppyforms-1.6.0/docs/examples.rst000066400000000000000000000146571263013462600206560ustar00rootroot00000000000000Example widgets =============== A date picker ------------- This snippet implements a rich date picker using the browser's date picker if the ``date`` input type is supported and falls back to a jQuery UI date picker. .. code-block:: python # forms.py import floppyforms as forms class DatePicker(forms.DateInput): template_name = 'datepicker.html' class Media: js = ( 'js/jquery.min.js', 'js/jquery-ui.min.js', ) css = { 'all': ( 'css/jquery-ui.css', ) } class DateForm(forms.Form): date = forms.DateField(widget=DatePicker) .. code-block:: jinja {# datepicker.html #} {% include "floppyforms/input.html" %} Here is how chromium renders it with its native (but sparse) date picker: .. image:: images/datepicker-chromium.png And here is the jQuery UI date picker as shown by Firefox: .. image:: images/datepicker-jquery-ui.png An autofocus input ------------------ A text input with the autofocus attribute and a fallback for browsers that doesn't support it. .. code-block:: python # forms.py import floppyforms as forms class AutofocusInput(forms.TextInput): template_name = 'autofocus.html' def get_context_data(self): self.attrs['autofocus'] = True return super(AutofocusInput, self).get_context_data() class AutofocusForm(forms.Form): text = forms.CharField(widget=AutofocusInput) .. code-block:: jinja {# autofocus.html #} {% include "floppyforms/input.html" %} A slider -------- A ``range`` input that uses the browser implementation or falls back to jQuery UI. .. code-block:: python # forms.py import floppyforms as forms class Slider(forms.RangeInput): min = 5 max = 20 step = 5 template_name = 'slider.html' class Media: js = ( 'js/jquery.min.js', 'js/jquery-ui.min.js', ) css = { 'all': ( 'css/jquery-ui.css', ) } class SlideForm(forms.Form): num = forms.IntegerField(widget=Slider) def clean_num(self): num = self.cleaned_data['num'] if not 5 <= num <= 20: raise forms.ValidationError("Enter a value between 5 and 20") if not num % 5 == 0: raise forms.ValidationError("Enter a multiple of 5") return num .. code-block:: jinja {# slider.html #} {% include "floppyforms/input.html" %}
Here is how chromium renders it with its native slider: .. image:: images/slider-chromium.png And here is the jQuery UI slider as shown by Firefox: .. image:: images/slider-jquery-ui.png A placeholder with fallback --------------------------- An ```` with a ``placeholder`` attribute and a javascript fallback for broader browser support. .. code-block:: python # forms.py import floppyforms as forms class PlaceholderInput(forms.TextInput): template_name = 'placeholder_input.html' class MyForm(forms.Form): text = forms.CharField(widget=PlaceholderInput( attrs={'placeholder': _('Some text here')}, )) .. code-block:: jinja {# placeholder_input.html #} {% include "floppyforms/input.html" %} An image clearable input with thumbnail --------------------------------------- If we have an image set for the field, display the image and propose to clear or to update. .. code-block:: python # forms.py import floppyforms as forms class ImageThumbnailFileInput(forms.ClearableFileInput): template_name = 'floppyforms/image_thumbnail.html' class ImageForm(forms.ModelForm): class Meta: model = Item fields = ('image',) widgets = {'image': ImageThumbnailFileInput} .. code-block:: django {# image_thumbnail.html #} {% load i18n %} {% if value.url %}{% trans "Currently:" %} {{ value }} {% if not required %}

{% else %}
{% endif %} {% trans "Change:" %} {% endif %} You now have your image: .. image:: images/image_with_thumbnail.png django-floppyforms-1.6.0/docs/geodjango.rst000066400000000000000000000347231263013462600207710ustar00rootroot00000000000000GeoDjango widgets ================= .. image:: images/geomcollection.png django-floppyforms provides fields and rich widgets for easy manipulation of GEOS geometry fields. All geometry types are supported thanks to OpenLayers and a custom WKT parser/serializer implementing some Django-specific tweaks. .. note:: Since GeoDjango doesn't provide any rich widget out of the box (except for the admin), the API described here is not trying to look like any existing API in GeoDjango. The geographic fields and widgets are provided under the ``floppyforms.gis`` namespace. Setting up ---------- To make sure you're ready to use the geographic widgets, follow the `installation instructions for GeoDjango`_ closely. You need to have ``'django.contrib.gis'`` in your ``INSTALLED_APPS`` setting. Next, you need to serve the javascript library provided by django-floppyforms (located in ``floppyforms/static/floppyforms/js/MapWidget.js``). You might want to use ``django.contrib.staticfiles``, so that the javascript library will be picked up automatically and gets served by the development server. Just make sure you run ``manage.py collectstatic`` once you deploy your project. .. _installation instructions for GeoDjango: https://docs.djangoproject.com/en/dev/ref/contrib/gis/install/ Widget types ------------ django-floppyforms provides **base widgets** and **geometry-specific widgets**: * **base widgets** are in charge of rendering a map from a specific map provider (Metacarta, Google Maps, OpenStreetMap…). They are not aware of the type of geometry, they need to be complemented by geometry-specific widgets. * **geometry-specific widgets** are here to make base widgets aware of the type of geometry to edit: is the geometry a point? A polygon? A collection? Geometry-specific widgets provides these information so that the corresponding controls are activated. To get a fully working geometry widget, you need to define a class that inherits from a base widget (to specify the map provider) and a geometry-specific widget (to specify the type of geometry you want to create). Here is a quick example: .. code-block:: python import floppyforms as forms class PointWidget(forms.gis.PointWidget, forms.gis.BaseGMapWidget): pass Here ``BaseGMapWidget`` is the base widget (i.e. I want to see a Google Map) and ``PointWidget`` is the geometry-specific widget (i.e. I want to draw a point on the map). Base Widgets ```````````` The following base widgets are provided: * ``BaseMetacartaWidget``: this base widget renders a map using the `Vector Level 0`_ map from `Metacarta`_. .. _Vector Level 0: http://earth-info.nga.mil/publications/vmap0.html .. _Metacarta: http://metacarta.com/ * ``BaseOsmWidget``: this base widget renders a map using `OpenStreetMap`_. .. _OpenStreetMap: http://www.openstreetmap.org/ * ``BaseGMapWidget``: this base widget renders a map using the Google Maps API. It uses the v3 javascript API, no API key is required. Geometry-specific widgets ````````````````````````` For each geographic model field, here are the corresponding form fields and form widgets provided by django-floppyforms: ======================= ======================= ======================== GeoDjango model field Floppyforms form field Floppyforms form widget ======================= ======================= ======================== PointField PointField PointWidget MultiPointField MultiPointField MultiPointWidget LineStringField LineStringField LineStringWidget MultiLineStringField MultiLineStringField MultiLineStringWidget PolygonField PolygonField PolygonWidget MultiPolygonField MultiPolygonField MultiPolygonWidget GeometryField GeometryField GeometryWidget GeometryCollectionField GeometryCollectionField GeometryCollectionWidget ======================= ======================= ======================== Each form field has a default form widget, using the corresponding geometry-specific widget and the Metacarta base widget. A form defined using nothing more than floppyforms fields will be displayed using the Metacarta WMS map service. For instance: .. code-block:: python # forms.py import floppyforms as forms class GeoForm(forms.Form): point = forms.gis.PointField() .. code-block:: jinja {# template.html #} {{ form.media }}
{% csrf_token %} {{ form.as_p }}

And the result will looks like this: .. image:: images/pointfield.png Customization ------------- The philosophy of this widgets library is to avoid building a complex layer of abstraction that would generate some javascript / OpenLayers code out of Python class attributes or methods. Everything that can be done in the template or JavaScript code should be done there. Therefore there are few options to customize the map on the widget classes. Only basic customization can be made in python, the rest should be done in the templates using the JavaScript library. Widget attributes and arguments ``````````````````````````````` The following attributes can be set on the widget class: * ``map_width``: the width of the map, in pixels. Default: 600. * ``map_height``: the height of the map, in pixels. Default: 400. * ``map_srid``: the SRID to use on the map. When existing geometries are edited, they are transformed to this SRID. The javascript code doesn't transform geometries so it's important to set this to the SRID used with your map provider. Default: 4326. * ``display_wkt``: whether to show the ``textarea`` in which the geometries are serialized. Usually useful for debugging. Default: ``False``. These options can be set as class attributes or passed into the ``attrs`` dictionnary used when instantiating a widget. The following snippets are equivalent: .. code-block:: python import floppyforms as forms class GMapPointWidget(forms.gis.PointWidget, forms.gis.BaseGMapWidget): pass class CustomPointWidget(GMapPointWidget): map_width = 1000 map_height = 700 class GeoForm(forms.Form): point = forms.gis.PointField(widget=CustomPointWidget) and: .. code-block:: python import floppyforms as forms class GMapPointWidget(forms.gis.PointWidget, forms.gis.BaseGMapWidget): pass class GeoForm(forms.Form): point = forms.gis.PointField(widget=GMapPointWidget(attrs={ 'map_width': 1000, 'map_height': 700, })) Of course, the traditional ``template_name`` class attribute is also supported. Template context ```````````````` The following variables are available in the template context: * ``ADMIN_MEDIA_PREFIX``: this setting, yes. It's useful to display some icons that are missing in OpenLayers. * ``LANGUAGE_BIDI``: the current locale direction. * ``attrs``: the traditional attrs dictionnary. This is the attrs dict for a ``textarea`` widget, it contains the ``id``, ``cols`` and ``rows`` attributes. * ``display_wkt``: the value from the widget class. * ``geom_type``: the OGR geometry type for the geometry being edited. * ``hidden``: set to ``False``, textareas can't be hidden. * ``is_collection``: whether the geometry is a collection. * ``is_linestring``: whether the geometry is a line string. * ``is_point``: whether the geometry is a point. * ``is_polygon``: whether the geometry is a polygon. * ``map_width``: the width, from the class attribute. * ``map_height``: the height, from the class attribute. * ``map_srid``: the SRID, from the class attribute. * ``module``: the name to use for the javascript object that contains the map. * ``name``: the name of the field. * ``required``: True if the field is required. * ``type``: the input type, ``None`` in this case. * ``value``: the WKT serialization of the geometry, expressed in the projection defined by ``map_srid``. Javascript library `````````````````` The javascript library provided by django-floppyforms relies on OpenLayers. It creates a map container based on a series of options. A minimal widget can be created like this: .. code-block:: javascript var options = { geom_type: OpenLayers.Geometry.Point, id: 'id_point', is_point: true, map_id: 'point_map', name: 'My awesome point' }; var point_map = new MapWidget(options); With these options, you need in your HTML code a `` django-floppyforms-1.6.0/floppyforms/templates/floppyforms/time.html000066400000000000000000000000471263013462600261240ustar00rootroot00000000000000{% extends "floppyforms/input.html" %} django-floppyforms-1.6.0/floppyforms/templates/floppyforms/url.html000066400000000000000000000000471263013462600257700ustar00rootroot00000000000000{% extends "floppyforms/input.html" %} django-floppyforms-1.6.0/floppyforms/templatetags/000077500000000000000000000000001263013462600224135ustar00rootroot00000000000000django-floppyforms-1.6.0/floppyforms/templatetags/__init__.py000066400000000000000000000000001263013462600245120ustar00rootroot00000000000000django-floppyforms-1.6.0/floppyforms/templatetags/floppyforms.py000066400000000000000000000573611263013462600253610ustar00rootroot00000000000000from collections import defaultdict from contextlib import contextmanager from django.conf import settings try: from django.forms.utils import ErrorList except ImportError: # Fall back to old module name for Django <= 1.5 from django.forms.util import ErrorList from django.template import (Library, Node, Variable, TemplateSyntaxError, VariableDoesNotExist) from django.template.base import token_kwargs from django.utils.functional import empty from ..compat import get_template register = Library() def is_formset(var): # We assume it is a formset if the var has these fields. significant_attributes = ('forms', 'management_form') return all(hasattr(var, attr) for attr in significant_attributes) def is_form(var): # We assume it is a form if the var has these fields. significant_attributes = ('is_bound', 'data', 'fields') return all(hasattr(var, attr) for attr in significant_attributes) def is_bound_field(var): # We assume it is a BoundField if the var has these fields. significant_attributes = ('as_widget', 'as_hidden', 'is_hidden') return all(hasattr(var, attr) for attr in significant_attributes) class ConfigFilter(object): """ Can be used as ``filter`` argument to ``FormConfig.configure()``. This filter matches to a bound field based on three criterias: It will return ``True`` if: * the bound field passed into the constructor equals the filtered field. * the string passed into the constructor equals the fields name. * the string passed into the constructor equals the field's class name. * the string passed into the constructor equals the field's widget class name. """ def __init__(self, var): self.var = var def __call__(self, bound_field): # when var is a bound_field ... # bound fields cannot be compared directly since form['field'] returns # a new instance every time it's called if hasattr(self.var, 'form') and hasattr(self.var, 'name'): if self.var.form is bound_field.form: if self.var.name == bound_field.name: return True if self.var == bound_field.name: return True # ignore 'object' in the mro, because it would be a match-all filter # anyway. And 'object' could clash with a field that is named the # same. for class_ in bound_field.field.__class__.__mro__: if class_.__name__ == 'object': continue if self.var == class_.__name__: return True for class_ in bound_field.field.widget.__class__.__mro__: if class_.__name__ == 'object': continue if self.var == class_.__name__: return True def __repr__(self): return "<%s: %r>" % (self.__class__.__name__, self.var) def default_label(bound_field, **kwargs): if bound_field: return bound_field.label def default_help_text(bound_field, **kwargs): if bound_field: return bound_field.field.help_text def default_widget(bound_field, **kwargs): if bound_field: return bound_field.field.widget def default_widget_template(bound_field, **kwargs): if bound_field: if hasattr(bound_field.field.widget, 'template_name'): return bound_field.field.widget.template_name return None class ConfigPopException(Exception): "pop() has been called more times than push()" pass class FormConfig(object): """ A stack of form-configuration dictionaries, where each configured value can be associated with a filter function that determines whether that value applies in specific situations. """ defaults = { 'layout': lambda **kwargs: 'floppyforms/layouts/default.html', 'row_template': lambda **kwargs: 'floppyforms/rows/default.html', 'label': default_label, 'help_text': default_help_text, 'widget': default_widget, 'widget_template': default_widget_template, } def __init__(self): self.dicts = [self._dict()] def _dict(self): return defaultdict(lambda: []) def push(self): d = self._dict() self.dicts.append(d) return d def pop(self): if len(self.dicts) == 1: raise ConfigPopException return self.dicts.pop() def configure(self, key, value, filter=None): """ Stores ``value`` under ``key``, optionally protected by given ``filter``. """ if filter is None: def filter(**kwargs): return True self.dicts[-1][key].append((value, filter)) def retrieve(self, key, **kwargs): """ Return most-recently-set value for ``key`` whose ``filter`` returns ``True`` when passed the given ``kwargs``. If no value is found and ``key`` has a default value: return ``self.defaults[key](**kwargs)`` """ for d in reversed(self.dicts): for value, filter in reversed(d[key]): if filter(**kwargs): return value if key not in self.defaults: return None return self.defaults[key](**kwargs) def retrieve_all(self, key, **kwargs): """ Returns a list of all applicable values for ``key``, ordered by most-recently-configured. """ values = [] for d in self.dicts: for value, filter in d[key]: if filter(**kwargs): values.insert(0, value) return values class BaseFormNode(Node): """ Base class for the form rendering tags. Holds methods to parse common arguments like "using