././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1632867932.9963214
django-bleach-0.9.0/ 0000755 0000765 0000024 00000000000 00000000000 013524 5 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867565.0
django-bleach-0.9.0/CHANGELOG.md 0000644 0000765 0000024 00000006751 00000000000 015346 0 ustar 00mwalker staff Version 0.9.0
=============
###### 28-09-2021
* Drop support for django <2.2
* Added support for django 4.0
Version 0.8.0
=============
###### 18-09-2021
Thank you to [Mark Gregson](https://github.com/MrkGrgsn) for providing the changes in this release!
* Fix for [#28](https://github.com/marksweb/django-bleach/issues/28): Return ``empty_value`` for any empty input value
* Fix for [#27](https://github.com/marksweb/django-bleach/issues/27): Mark cleaned data as template safe
* Fix for [#25](https://github.com/marksweb/django-bleach/issues/25): Respect the ``form_class`` argument
* Fix custom widget tests [#34](https://github.com/marksweb/django-bleach/pulls/34)
Version 0.7.2
=============
###### 27-07-2021
* Fix for [#23](https://github.com/marksweb/django-bleach/issues/23): `kwargs` being lost in the default form field.
Version 0.7.1
=============
###### 23-07-2021
* Fix for [#21](https://github.com/marksweb/django-bleach/issues/21): default form field not respecting required fields.
Version 0.7.0
=============
###### 09-07-2021
* Default form field set to `forms.BleachField` for `models.BleachField` (Thanks [Alirezaja1384](https://github.com/Alirezaja1384))
* Introduced testing against Python 3.9
Version 0.6.1
=============
###### 07-11-2019
* Handle `None` as an input value of template tags (Thanks [pegler](https://github.com/pegler))
Version 0.6.0
=============
###### 18-10-2019
* Introduced testing against Python 3.8
* Drop support for Django <1.11
* Test coverage at 100%
Version 0.5.3
=============
###### 16-04-2019
* Fix for `BleachField` set to allow `blank` or `null`. (Thanks [denisroldan](https://github.com/denisroldan))
Version 0.5.2
=============
###### 15-03-2019
* Fix for `BleachField` receiving a `None` value. (Thanks [MrkGrgsn](https://github.com/MrkGrgsn))
Version 0.5.1
=============
###### 12-02-2019
* 100% coverage achieved
* Changelog updated with `0.5.0` changes. (Thanks [dyve](https://github.com/dyve))
Version 0.5.0
=============
###### 02-02-2019
* Added support for bleach's `allowed_protocols` kwarg. (Thanks [blag](https://github.com/blag))
* Bleach dependency is now `>=1.5.0`
Version 0.4.1
=============
###### 24-01-2019
* Option to pass *allowed tags* to the `bleach` template filter added by [Rafał Selewońko](https://github.com/seler).
* Moved project to Github.
Version 0.4.0
=============
###### 18-12-2018
* Added support for django>=1.9
* Ensure that the `model_instance` field gets updated with the clean value
Version 0.3.0
=============
###### 20-09-2014
* The `BleachField` model field now does its own sanitisation,
and does *not* specify a default form field or widget.
Developers are expected to provide their own widget as needed.
Version 0.2.1
=============
###### 02-09-2014
* Make the package python3 compatible.
Version 0.2.0
=============
###### 14-02-2014
* Add `bleach_linkify` template filter from [whitehat2k13](https://bitbucket.org/%7B66836148-7eee-4894-acec-e073b30499ee%7D/)
Version 0.1.5
=============
###### 25-09-2013
Version 0.1.4
=============
###### 03-06-2013
Version 0.1.3
=============
###### 22-08-2012
* Add missing `templatetags` package, by using `find_packages()`
* Correct templatetag name: ``bleach.py`` -> ``bleach_tags.py``
Version 0.1.2
=============
###### 13-08-2012
* Fix south migration bug
Version 0.1.1
=============
###### 13-08-2012
* add south_triple_field for south integration
* clean up files to meet pep8 compliance
Version 0.1.0
=============
###### 13-08-2012
* Initial release
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1548369611.0
django-bleach-0.9.0/LICENSE 0000644 0000765 0000024 00000002053 00000000000 014531 0 ustar 00mwalker staff MIT License
Copyright (c) 2018 Mark Walker
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1571408883.0
django-bleach-0.9.0/MANIFEST.in 0000644 0000765 0000024 00000000301 00000000000 015254 0 ustar 00mwalker staff include LICENSE
include README.rst
include CHANGELOG.md
include docs/*.rst
prune docs/_build
global-exclude coverage.xml
global-exclude .coverage
recursive-exclude * *.pyc __pycache__ .DS_Store ././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1632867932.9968657
django-bleach-0.9.0/PKG-INFO 0000644 0000765 0000024 00000017461 00000000000 014632 0 ustar 00mwalker staff Metadata-Version: 1.1
Name: django-bleach
Version: 0.9.0
Summary: Easily use bleach with Django models and templates
Home-page: https://github.com/marksweb/django-bleach
Author: Tim Heap & Mark Walker
Author-email: theshow@gmail.com
License: MIT
Description: django-bleach - Bleach and sanitise user HTML
=============================================
.. image:: https://readthedocs.org/projects/django-bleach/badge/?version=latest
:target: https://django-bleach.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: http://img.shields.io/pypi/v/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: Latest Version
.. image:: http://img.shields.io/pypi/l/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: License
|
.. image:: https://codecov.io/gh/marksweb/django-bleach/branch/master/graph/badge.svg
:target: https://codecov.io/gh/marksweb/django-bleach
.. image:: https://api.codacy.com/project/badge/Grade/c34f923ab0a84a6f96728866c749d511
:alt: Codacy Badge
:target: https://app.codacy.com/app/marksweb/django-bleach?utm_source=github.com&utm_medium=referral&utm_content=marksweb/django-bleach&utm_campaign=Badge_Grade_Dashboard
.. image:: http://img.shields.io/pypi/dm/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: Downloads
|
Bleach_ is a Python module that takes any HTML input, and returns
valid, sanitised HTML that contains only an allowed subset of HTML tags,
attributes and styles. ``django-bleach`` is a Django app that makes using
``bleach`` extremely easy.
`Read the documentation here`_.
Setup
-----
1. Install ``django-bleach`` via ``pip``::
pip install django-bleach
2. Add ``django-bleach`` to your ``INSTALLED_APPS``::
INSTALLED_APPS = [
# ...
'django_bleach',
# ...
]
3. Select some sensible defaults for the allowed tags, attributes and styles;
and the behaviour when unknown tags are encountered. Each of these are
optional, and default to using the ``bleach`` defaults. See the
`bleach documentation`_::
# Which HTML tags are allowed
BLEACH_ALLOWED_TAGS = ['p', 'b', 'i', 'u', 'em', 'strong', 'a']
# Which HTML attributes are allowed
BLEACH_ALLOWED_ATTRIBUTES = ['href', 'title', 'style']
# Which CSS properties are allowed in 'style' attributes (assuming
# style is an allowed attribute)
BLEACH_ALLOWED_STYLES = [
'font-family', 'font-weight', 'text-decoration', 'font-variant']
# Strip unknown tags if True, replace with HTML escaped characters if
# False
BLEACH_STRIP_TAGS = True
# Strip comments, or leave them in.
BLEACH_STRIP_COMMENTS = False
4. Select the default widget for bleach fields. This defaults to
``django.forms.Textarea``, but you will probably want to replace it with a
WYSIWYG editor, or something similar::
# Use the CKEditorWidget for bleached HTML fields
BLEACH_DEFAULT_WIDGET = 'wysiwyg.widgets.WysiwygWidget'
I use `django-ckeditor`_ in my projects, but what you use is up to you.
Usage
-----
In your models
**************
``django-bleach`` provides three ways of creating bleached output. The simplest
way of including user-editable HTML content that is automatically sanitised is
by using the ``BleachField`` model field::
# in app/models.py
from django import models
from django_bleach.models import BleachField
class Post(models.Model):
title = models.CharField()
content = BleachField()
# ...
``BleachField`` takes the following arguments, to customise the output of
``bleach``. See the `bleach documentation`_ for their use:
* ``allowed_tags``
* ``allowed_attributes``
* ``allowed_styles``
* ``strip_tags``
* ``strip_comments``
In addition to the ``bleach``-specific arguments, the ``BleachField`` model field
accepts all of the normal field attributes. Behind the scenes, it is a
``TextField``, and accepts all the same arguments as the default ``TextField`` does.
The ``BleachField`` model field sanitises its value before it is saved to the
database and is marked safe so it can be immediately rendered in a template
without further intervention.
In model forms, ``BleachField`` model field are represented with the
``BleachField`` form field by default.
In your forms
*************
A ``BleachField`` form field is provided. This field sanitises HTML input from
the user, and presents safe, clean HTML to your Django application and the
returned value is marked safe for immediate rendering.
In your templates
*****************
If you have a piece of content from somewhere that needs to be printed in a
template, you can use the ``bleach`` filter::
{% load bleach_tags %}
{{ some_unsafe_content|bleach }}
If filter has no arguments it uses default settings defined in your
application settings. You can override allowed tags by specifying them
as a parameter to the filter::
{{ some_unsafe_content|bleach:"p,span" }}
There is also ``bleach_linkify`` which uses the linkify_ function of bleach
which converts URL-like strings in an HTML fragment to links
This function converts strings that look like URLs, domain names and email
addresses in text that may be an HTML fragment to links, while preserving:
1. links already in the string
2. urls found in attributes
3. email addresses
.. _bleach: https://github.com/mozilla/bleach
.. _Read the documentation here: https://django-bleach.readthedocs.io/
.. _bleach documentation: https://bleach.readthedocs.io/en/latest/clean.html
.. _django-ckeditor: https://github.com/shaunsephton/django-ckeditor
.. _linkify: https://bleach.readthedocs.io/en/latest/linkify.html?highlight=linkify#bleach.linkify "linkify"
Platform: UNKNOWN
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Framework :: Django :: 2.2
Classifier: Framework :: Django :: 3.0
Classifier: Framework :: Django :: 3.1
Classifier: Framework :: Django :: 3.2
Classifier: Framework :: Django :: 4.0
Classifier: Development Status :: 5 - Production/Stable
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632856487.0
django-bleach-0.9.0/README.rst 0000644 0000765 0000024 00000013024 00000000000 015213 0 ustar 00mwalker staff django-bleach - Bleach and sanitise user HTML
=============================================
.. image:: https://readthedocs.org/projects/django-bleach/badge/?version=latest
:target: https://django-bleach.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: http://img.shields.io/pypi/v/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: Latest Version
.. image:: http://img.shields.io/pypi/l/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: License
|
.. image:: https://codecov.io/gh/marksweb/django-bleach/branch/master/graph/badge.svg
:target: https://codecov.io/gh/marksweb/django-bleach
.. image:: https://api.codacy.com/project/badge/Grade/c34f923ab0a84a6f96728866c749d511
:alt: Codacy Badge
:target: https://app.codacy.com/app/marksweb/django-bleach?utm_source=github.com&utm_medium=referral&utm_content=marksweb/django-bleach&utm_campaign=Badge_Grade_Dashboard
.. image:: http://img.shields.io/pypi/dm/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: Downloads
|
Bleach_ is a Python module that takes any HTML input, and returns
valid, sanitised HTML that contains only an allowed subset of HTML tags,
attributes and styles. ``django-bleach`` is a Django app that makes using
``bleach`` extremely easy.
`Read the documentation here`_.
Setup
-----
1. Install ``django-bleach`` via ``pip``::
pip install django-bleach
2. Add ``django-bleach`` to your ``INSTALLED_APPS``::
INSTALLED_APPS = [
# ...
'django_bleach',
# ...
]
3. Select some sensible defaults for the allowed tags, attributes and styles;
and the behaviour when unknown tags are encountered. Each of these are
optional, and default to using the ``bleach`` defaults. See the
`bleach documentation`_::
# Which HTML tags are allowed
BLEACH_ALLOWED_TAGS = ['p', 'b', 'i', 'u', 'em', 'strong', 'a']
# Which HTML attributes are allowed
BLEACH_ALLOWED_ATTRIBUTES = ['href', 'title', 'style']
# Which CSS properties are allowed in 'style' attributes (assuming
# style is an allowed attribute)
BLEACH_ALLOWED_STYLES = [
'font-family', 'font-weight', 'text-decoration', 'font-variant']
# Strip unknown tags if True, replace with HTML escaped characters if
# False
BLEACH_STRIP_TAGS = True
# Strip comments, or leave them in.
BLEACH_STRIP_COMMENTS = False
4. Select the default widget for bleach fields. This defaults to
``django.forms.Textarea``, but you will probably want to replace it with a
WYSIWYG editor, or something similar::
# Use the CKEditorWidget for bleached HTML fields
BLEACH_DEFAULT_WIDGET = 'wysiwyg.widgets.WysiwygWidget'
I use `django-ckeditor`_ in my projects, but what you use is up to you.
Usage
-----
In your models
**************
``django-bleach`` provides three ways of creating bleached output. The simplest
way of including user-editable HTML content that is automatically sanitised is
by using the ``BleachField`` model field::
# in app/models.py
from django import models
from django_bleach.models import BleachField
class Post(models.Model):
title = models.CharField()
content = BleachField()
# ...
``BleachField`` takes the following arguments, to customise the output of
``bleach``. See the `bleach documentation`_ for their use:
* ``allowed_tags``
* ``allowed_attributes``
* ``allowed_styles``
* ``strip_tags``
* ``strip_comments``
In addition to the ``bleach``-specific arguments, the ``BleachField`` model field
accepts all of the normal field attributes. Behind the scenes, it is a
``TextField``, and accepts all the same arguments as the default ``TextField`` does.
The ``BleachField`` model field sanitises its value before it is saved to the
database and is marked safe so it can be immediately rendered in a template
without further intervention.
In model forms, ``BleachField`` model field are represented with the
``BleachField`` form field by default.
In your forms
*************
A ``BleachField`` form field is provided. This field sanitises HTML input from
the user, and presents safe, clean HTML to your Django application and the
returned value is marked safe for immediate rendering.
In your templates
*****************
If you have a piece of content from somewhere that needs to be printed in a
template, you can use the ``bleach`` filter::
{% load bleach_tags %}
{{ some_unsafe_content|bleach }}
If filter has no arguments it uses default settings defined in your
application settings. You can override allowed tags by specifying them
as a parameter to the filter::
{{ some_unsafe_content|bleach:"p,span" }}
There is also ``bleach_linkify`` which uses the linkify_ function of bleach
which converts URL-like strings in an HTML fragment to links
This function converts strings that look like URLs, domain names and email
addresses in text that may be an HTML fragment to links, while preserving:
1. links already in the string
2. urls found in attributes
3. email addresses
.. _bleach: https://github.com/mozilla/bleach
.. _Read the documentation here: https://django-bleach.readthedocs.io/
.. _bleach documentation: https://bleach.readthedocs.io/en/latest/clean.html
.. _django-ckeditor: https://github.com/shaunsephton/django-ckeditor
.. _linkify: https://bleach.readthedocs.io/en/latest/linkify.html?highlight=linkify#bleach.linkify "linkify"
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1632867932.9019504
django-bleach-0.9.0/django_bleach/ 0000755 0000765 0000024 00000000000 00000000000 016264 5 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867565.0
django-bleach-0.9.0/django_bleach/__init__.py 0000644 0000765 0000024 00000000166 00000000000 020400 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
__author__ = "Tim Heap & Mark Walker"
__version__ = "0.9.0"
VERSION = __version__.split(".")
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1631920575.0
django-bleach-0.9.0/django_bleach/forms.py 0000644 0000765 0000024 00000004736 00000000000 017776 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
import bleach
from django import forms
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
from django.utils.safestring import mark_safe
from importlib import import_module
from django_bleach.utils import get_bleach_default_options
def load_widget(path):
""" Load custom widget for the form field """
i = path.rfind(".")
module, attr = path[:i], path[i + 1:]
try:
mod = import_module(module)
except (ImportError, ValueError) as e:
error_message = "Error importing widget for BleachField %s: '%s'"
raise ImproperlyConfigured(error_message % (path, e))
try:
cls = getattr(mod, attr)
except AttributeError:
raise ImproperlyConfigured(
"Module '%s' does not define a '%s' widget" % (module, attr)
)
return cls
def get_default_widget():
""" Get the default widget or the widget defined in settings """
default_widget = forms.Textarea
if hasattr(settings, "BLEACH_DEFAULT_WIDGET"):
default_widget = load_widget(settings.BLEACH_DEFAULT_WIDGET)
return default_widget
class BleachField(forms.CharField):
""" Bleach form field """
empty_values = [None, "", [], (), {}]
def __init__(self, allowed_tags=None, allowed_attributes=None,
allowed_styles=None, allowed_protocols=None,
strip_comments=None, strip_tags=None, *args, **kwargs):
self.widget = get_default_widget()
super(BleachField, self).__init__(*args, **kwargs)
self.bleach_options = get_bleach_default_options()
if allowed_tags is not None:
self.bleach_options["tags"] = allowed_tags
if allowed_attributes is not None:
self.bleach_options["attributes"] = allowed_attributes
if allowed_styles is not None:
self.bleach_options["styles"] = allowed_styles
if allowed_protocols is not None:
self.bleach_options["protocols"] = allowed_protocols
if strip_tags is not None:
self.bleach_options["strip"] = strip_tags
if strip_comments is not None:
self.bleach_options["strip_comments"] = strip_comments
def to_python(self, value):
"""
Strips any dodgy HTML tags from the input.
Mark the return value as template safe.
"""
if value in self.empty_values:
return self.empty_value
return mark_safe(bleach.clean(value, **self.bleach_options))
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632856487.0
django-bleach-0.9.0/django_bleach/models.py 0000644 0000765 0000024 00000005034 00000000000 020123 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
from django.db import models
from django.utils.safestring import mark_safe
from bleach import clean
from . import forms
from .utils import get_bleach_default_options
class BleachField(models.TextField):
def __init__(self, allowed_tags=None, allowed_attributes=None,
allowed_styles=None, allowed_protocols=None,
strip_tags=None, strip_comments=None, *args, **kwargs):
super(BleachField, self).__init__(*args, **kwargs)
self.bleach_kwargs = get_bleach_default_options()
if allowed_tags:
self.bleach_kwargs["tags"] = allowed_tags
if allowed_attributes:
self.bleach_kwargs["attributes"] = allowed_attributes
if allowed_styles:
self.bleach_kwargs["styles"] = allowed_styles
if allowed_protocols:
self.bleach_kwargs["protocols"] = allowed_protocols
if strip_tags:
self.bleach_kwargs["strip"] = strip_tags
if strip_comments:
self.bleach_kwargs["strip_comments"] = strip_comments
def formfield(self, form_class=forms.BleachField, **kwargs):
""" Makes the field for a ModelForm """
# If field doesn't have any choices add kwargs expected by BleachField.
if not self.choices:
kwargs.setdefault("widget", forms.get_default_widget())
kwargs.update({
"max_length": self.max_length,
"allowed_tags": self.bleach_kwargs.get("tags"),
"allowed_attributes": self.bleach_kwargs.get("attributes"),
"allowed_styles": self.bleach_kwargs.get("styles"),
"allowed_protocols": self.bleach_kwargs.get("protocols"),
"strip_tags": self.bleach_kwargs.get("strip"),
"strip_comments": self.bleach_kwargs.get("strip_comments"),
"required": not self.blank,
})
return super(BleachField, self).formfield(form_class=form_class, **kwargs)
def pre_save(self, model_instance, add):
data = getattr(model_instance, self.attname)
if data is None:
return data
clean_value = clean(data, **self.bleach_kwargs) if data else ""
setattr(model_instance, self.attname, mark_safe(clean_value))
return clean_value
def from_db_value(self, value, expression, connection):
if value is None:
return value
# Values are sanitised before saving, so any value returned from the DB
# is safe to render unescaped.
return mark_safe(value)
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1632867932.9321053
django-bleach-0.9.0/django_bleach/templatetags/ 0000755 0000765 0000024 00000000000 00000000000 020756 5 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1607436691.0
django-bleach-0.9.0/django_bleach/templatetags/__init__.py 0000644 0000765 0000024 00000000000 00000000000 023055 0 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1626701887.0
django-bleach-0.9.0/django_bleach/templatetags/bleach_tags.py 0000644 0000765 0000024 00000002045 00000000000 023565 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
import bleach
from django import template
from django.utils.safestring import mark_safe
from django_bleach.utils import get_bleach_default_options
register = template.Library()
@register.filter(name="bleach")
def bleach_value(value, tags=None):
if value is None:
return None
bleach_args = get_bleach_default_options()
if tags is not None:
args = bleach_args.copy()
args["tags"] = tags.split(",")
else:
args = bleach_args
bleached_value = bleach.clean(value, **args)
return mark_safe(bleached_value)
@register.filter
def bleach_linkify(value):
"""
Convert URL-like strings in an HTML fragment to links
This function converts strings that look like URLs, domain names and email
addresses in text that may be an HTML fragment to links, while preserving:
1. links already in the string
2. urls found in attributes
3. email addresses
"""
if value is None:
return None
return bleach.linkify(value, parse_email=True)
././@PaxHeader 0000000 0000000 0000000 00000000032 00000000000 010210 x ustar 00 26 mtime=1632867932.98095
django-bleach-0.9.0/django_bleach/tests/ 0000755 0000765 0000024 00000000000 00000000000 017426 5 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1548430527.0
django-bleach-0.9.0/django_bleach/tests/__init__.py 0000644 0000765 0000024 00000000000 00000000000 021525 0 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1631920575.0
django-bleach-0.9.0/django_bleach/tests/test_forms.py 0000644 0000765 0000024 00000015716 00000000000 022177 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
from django import forms
from django.test import TestCase, override_settings
from django.utils.safestring import SafeString
from django_bleach.forms import BleachField
from testproject.constants import (
ALLOWED_ATTRIBUTES,
ALLOWED_PROTOCOLS,
ALLOWED_STYLES,
ALLOWED_TAGS
)
from testproject.forms import BleachForm, CustomBleachWidget
class TestBleachField(TestCase):
def test_empty(self):
""" Test that the empty_value arg is returned for any input empty value """
for requested_empty_value in ('', None):
field = BleachField(empty_value=requested_empty_value)
for empty_value in field.empty_values:
self.assertEqual(field.to_python(empty_value), requested_empty_value)
def test_return_type(self):
""" Test bleached values are SafeString objects """
field = BleachField()
self.assertIsInstance(field.to_python("some text"), SafeString)
def test_bleaching(self):
""" Test values are bleached """
test_data = {
'no_tags': "
Heading
",
'no_strip': "Heading
",
'bleach_strip': ""
"",
'bleach_attrs': "google.com",
'bleach_styles': "item"
}
form = BleachForm(data=test_data)
form.is_valid()
self.assertEqual(
form.cleaned_data['no_tags'], 'Heading'
)
self.assertEqual(
form.cleaned_data['no_strip'],
'<h1>Heading</h1>'
)
self.assertEqual(
form.cleaned_data['bleach_strip'],
'alert("Hello World")'
)
self.assertEqual(
form.cleaned_data['bleach_attrs'],
'google.com'
)
self.assertNotEqual(
form.cleaned_data['bleach_styles'],
test_data['bleach_styles']
)
def test_tags(self):
""" Test allowed tags are rendered"""
test_data = {
'no_tags': "No tags here
",
'no_strip': "No tags here",
'bleach_strip': "",
'bleach_attrs': "google.com",
'bleach_styles': "item"
}
form = BleachForm(data=test_data)
form.is_valid()
self.assertEqual(form.cleaned_data['no_tags'], "No tags here")
self.assertEqual(form.cleaned_data['no_strip'], "No tags here")
self.assertEqual(
form.cleaned_data['bleach_strip'],
test_data['bleach_strip']
)
self.assertEqual(
form.cleaned_data['bleach_attrs'],
test_data['bleach_attrs']
)
self.assertEqual(
form.cleaned_data['bleach_styles'],
test_data['bleach_styles']
)
def test_attrs(self):
""" Test allowed attributes are rendered """
list_html = ""
test_data = {
'no_strip': "",
'no_tags': list_html,
'bleach_strip': list_html,
'bleach_attrs': list_html,
'bleach_styles': list_html
}
form = BleachForm(data=test_data)
form.is_valid()
self.assertEqual(form.cleaned_data['no_tags'], 'onetwo')
self.assertEqual(
form.cleaned_data['bleach_strip'],
''
)
self.assertEqual(
form.cleaned_data['bleach_attrs'],
test_data['bleach_strip']
)
self.assertEqual(
form.cleaned_data['bleach_styles'],
''
)
@override_settings(BLEACH_DEFAULT_WIDGET='testproject.forms.CustomBleachWidget')
class TestCustomWidget(TestCase):
def setUp(self):
class CustomForm(forms.Form):
# Define form inside function with overridden settings so
# get_default_widget() sees the modified setting.
no_tags = BleachField(
max_length=100,
strip_tags=True,
allowed_tags=[]
)
no_strip = BleachField(
max_length=100,
allowed_tags=None,
allowed_attributes=None
)
bleach_strip = BleachField(
max_length=100,
strip_comments=True,
strip_tags=True,
allowed_tags=ALLOWED_TAGS
)
bleach_attrs = BleachField(
max_length=100,
strip_tags=False,
allowed_tags=ALLOWED_TAGS,
allowed_protocols=ALLOWED_PROTOCOLS,
allowed_attributes=ALLOWED_ATTRIBUTES
)
bleach_styles = BleachField(
max_length=100,
strip_tags=False,
allowed_attributes=['style'],
allowed_tags=ALLOWED_TAGS,
allowed_styles=ALLOWED_STYLES
)
self.CustomForm = CustomForm
def test_custom_widget_type(self):
""" Test widget class matches BLEACH_DEFAULT_WIDGET """
for field in self.CustomForm().fields.values():
self.assertIsInstance(field.widget, CustomBleachWidget)
def test_custom_widget_bleaches_content(self):
"""
Test input is bleached according to config while using a custom
widget
"""
test_data = {
'no_tags': 'Heading
',
'no_strip': 'Heading
',
'bleach_strip': ''
'',
'bleach_attrs': (
'google.com'
'google.com'
),
'bleach_styles': 'item'
}
form = self.CustomForm(data=test_data)
form.is_valid()
self.assertEqual(
form.cleaned_data['no_tags'], 'Heading'
)
self.assertEqual(
form.cleaned_data['no_strip'],
'<h1>Heading</h1>'
)
self.assertEqual(
form.cleaned_data['bleach_strip'],
'alert("Hello World")'
)
self.assertEqual(
form.cleaned_data['bleach_attrs'],
'google.comgoogle.com'
)
self.assertNotEqual(
form.cleaned_data['bleach_styles'],
test_data['bleach_styles']
)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1631920575.0
django-bleach-0.9.0/django_bleach/tests/test_modelformfield.py 0000644 0000765 0000024 00000007307 00000000000 024036 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
from django import forms
from django.test import TestCase, override_settings
from django_bleach import forms as bleach_forms
from testproject.forms import CustomBleachWidget
from testproject.models import Person
from .test_models import BleachContent
class BleachContentModelForm(forms.ModelForm):
class Meta:
model = BleachContent
fields = '__all__'
class TestModelFormField(TestCase):
def setUp(self):
model_form = BleachContentModelForm()
self.form_field = model_form.fields['content']
self.choice_form_field = model_form.fields['choice']
self.blank_field_form_field = model_form.fields['blank_field']
self.model_field = BleachContent()._meta.get_field('content')
def test_formfield_type(self):
"""
Check content's form field is instance of BleachField
"""
self.assertIsInstance(self.form_field, bleach_forms.BleachField)
def test_default_widget_type(self):
"""
Widget class is Textarea when BLEACH_DEFAULT_WIDGET is not set.
"""
form = forms.modelform_factory(Person, fields='__all__')()
self.assertIsInstance(
form.fields['biography'].widget, forms.Textarea,
)
@override_settings(
BLEACH_DEFAULT_WIDGET='testproject.forms.CustomBleachWidget'
)
def test_custom_widget_type(self):
"""
Widget class matches BLEACH_DEFAULT_WIDGET setting.
"""
form = forms.modelform_factory(Person, fields='__all__')()
self.assertIsInstance(
form.fields['biography'].widget, CustomBleachWidget
)
@override_settings(
BLEACH_DEFAULT_WIDGET='testproject.forms.CustomBleachWidget'
)
def test_widget_override(self):
"""
Widget class matches widget class specified in overrides.
"""
form = forms.modelform_factory(
Person,
fields='__all__',
widgets={"biography": CustomBleachWidget},
)()
self.assertIsInstance(
form.fields['biography'].widget, CustomBleachWidget
)
def test_same_allowed_args(self):
"""
Check model and form's allowed arguments (tags, attributes, ...) are same
"""
form_allowed_args: dict = self.form_field.bleach_options
model_allowed_args: dict = self.model_field.bleach_kwargs
self.assertEqual(model_allowed_args, form_allowed_args)
def test_with_choices(self):
"""
Check if choices specified, use TextField's default widget (Select).
"""
form_field_widget = self.choice_form_field.widget.__class__
self.assertEqual(form_field_widget, forms.widgets.Select)
def test_optional_field(self):
"""
Check for the required flag on fields with `blank=True`
"""
self.assertEqual(self.blank_field_form_field.required, False)
def test_required_field(self):
"""
Check for the required flag on fields
"""
self.assertEqual(self.form_field.required, True)
class CustomBleachedFormField(bleach_forms.BleachField):
...
class OverriddenBleachContentModelForm(forms.ModelForm):
class Meta:
model = BleachContent
fields = '__all__'
field_classes = {
"content": CustomBleachedFormField,
}
class TestModelFormFieldOverrides(TestCase):
def setUp(self):
model_form = OverriddenBleachContentModelForm()
self.form_field = model_form.fields['content']
def test_formfield_type(self):
"""
Check content's form field is instance of CustomBleachedFormField.
"""
self.assertIsInstance(self.form_field, CustomBleachedFormField)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632856487.0
django-bleach-0.9.0/django_bleach/tests/test_models.py 0000644 0000765 0000024 00000007203 00000000000 022324 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
from django.db import models
from django.test import TestCase
from django.utils.safestring import SafeString
from django_bleach.models import BleachField
from testproject.constants import (
ALLOWED_ATTRIBUTES, ALLOWED_PROTOCOLS,
ALLOWED_STYLES, ALLOWED_TAGS
)
class BleachContent(models.Model):
""" Bleach test model"""
CHOICES = (
('f', 'first choice'),
('s', 'second choice')
)
content = BleachField(
allowed_attributes=ALLOWED_ATTRIBUTES,
allowed_protocols=ALLOWED_PROTOCOLS,
allowed_styles=ALLOWED_STYLES,
allowed_tags=ALLOWED_TAGS,
strip_comments=True,
strip_tags=True
)
choice = BleachField(choices=CHOICES)
blank_field = BleachField(blank=True)
null_field = BleachField(blank=True, null=True)
class TestBleachModelField(TestCase):
""" Test model field """
def test_bleaching(self):
""" Test values are bleached """
test_data = {
'no_tags': "Heading
",
'no_strip': "Heading
",
'bleach_strip': """""",
'bleach_attrs': "google.com",
'bleach_styles': "item",
'bleach_comment': "",
}
expected_values = {
'no_tags': "Heading",
'no_strip': "Heading",
'bleach_strip': """alert("Hello World")""",
'bleach_attrs':
"google.com",
'bleach_styles': "item",
'bleach_comment': ""
}
for key, value in test_data.items():
obj = BleachContent.objects.create(content=value)
self.assertEqual(obj.content, expected_values[key])
def test_retrieved_values_are_template_safe(self):
obj = BleachContent.objects.create(content="some content")
obj.refresh_from_db()
self.assertIsInstance(obj.content, SafeString)
obj = BleachContent.objects.create(content="")
obj.refresh_from_db()
self.assertIsInstance(obj.content, SafeString)
def test_saved_values_are_template_safe(self):
obj = BleachContent(content="some content")
obj.save()
self.assertIsInstance(obj.content, SafeString)
obj = BleachContent(content="")
obj.save()
self.assertIsInstance(obj.content, SafeString)
def test_saved_none_values_are_none(self):
obj = BleachContent(null_field=None)
obj.save()
self.assertIsNone(obj.null_field)
class BleachNullableContent(models.Model):
""" Bleach test model"""
content = BleachField(
allowed_attributes=ALLOWED_ATTRIBUTES,
allowed_protocols=ALLOWED_PROTOCOLS,
allowed_styles=ALLOWED_STYLES,
allowed_tags=ALLOWED_TAGS,
strip_comments=True,
strip_tags=True,
blank=True,
null=True
)
class TestBleachNullableModelField(TestCase):
""" Test model field """
def test_bleaching(self):
""" Test values are bleached """
test_data = {
'none': None,
'empty': "",
'whitespaces': " ",
'linebreak': "\n",
}
expected_values = {
'none': None,
'empty': "",
'whitespaces': " ",
'linebreak': "\n",
}
for key, value in test_data.items():
obj = BleachNullableContent.objects.create(content=value)
self.assertEqual(obj.content, expected_values[key])
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1625789754.0
django-bleach-0.9.0/django_bleach/tests/test_settings.py 0000644 0000765 0000024 00000005554 00000000000 022710 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
from django.core.exceptions import ImproperlyConfigured
from django.forms import Textarea
from django.test import TestCase, override_settings
from mock import patch
from django_bleach.forms import get_default_widget
from django_bleach.utils import get_bleach_default_options
from testproject.constants import (
ALLOWED_ATTRIBUTES, ALLOWED_PROTOCOLS,
ALLOWED_STYLES, ALLOWED_TAGS,
)
from testproject.forms import CustomBleachWidget
class TestBleachOptions(TestCase):
@patch('django_bleach.utils.settings',
BLEACH_ALLOWED_ATTRIBUTES=ALLOWED_ATTRIBUTES)
def test_custom_attrs(self, settings):
bleach_args = get_bleach_default_options()
self.assertEqual(bleach_args['attributes'], ALLOWED_ATTRIBUTES)
@patch('django_bleach.utils.settings',
BLEACH_ALLOWED_PROTOCOLS=ALLOWED_PROTOCOLS)
def test_custom_proto(self, settings):
bleach_args = get_bleach_default_options()
self.assertEqual(bleach_args['protocols'], ALLOWED_PROTOCOLS)
@patch('django_bleach.utils.settings',
BLEACH_ALLOWED_STYLES=ALLOWED_STYLES)
def test_custom_styles(self, settings):
bleach_args = get_bleach_default_options()
self.assertEqual(bleach_args['styles'], ALLOWED_STYLES)
@patch('django_bleach.utils.settings', BLEACH_ALLOWED_TAGS=ALLOWED_TAGS)
def test_custom_tags(self, settings):
bleach_args = get_bleach_default_options()
self.assertEqual(bleach_args['tags'], ALLOWED_TAGS)
@patch('django_bleach.utils.settings', BLEACH_STRIP_TAGS=True)
def test_strip_tags(self, settings):
bleach_args = get_bleach_default_options()
self.assertEqual(bleach_args['strip'], True)
@patch('django_bleach.utils.settings', BLEACH_STRIP_COMMENTS=True)
def test_strip_comments(self, settings):
bleach_args = get_bleach_default_options()
self.assertEqual(bleach_args['strip_comments'], True)
class TestDefaultWidget(TestCase):
""" Test form field widgets """
@override_settings(BLEACH_DEFAULT_WIDGET='django.forms.widgets.Textarea')
def test_default_widget(self):
self.assertEqual(get_default_widget(), Textarea)
@patch('django_bleach.forms.settings',
BLEACH_DEFAULT_WIDGET='testproject.forms.CustomBleachWidget')
def test_custom_widget(self, settings):
self.assertEqual(get_default_widget(), CustomBleachWidget)
@patch('django_bleach.forms.settings',
BLEACH_DEFAULT_WIDGET='testproject.forms.NoneExistentWidget')
def test_attribute_err(self, settings):
with self.assertRaises(ImproperlyConfigured):
get_default_widget()
@patch('django_bleach.forms.settings',
BLEACH_DEFAULT_WIDGET='testproject.forms2.CustomBleachWidget')
def test_import_err(self, settings):
with self.assertRaises(ImproperlyConfigured):
get_default_widget()
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1607436547.0
django-bleach-0.9.0/django_bleach/tests/test_templatetags.py 0000644 0000765 0000024 00000004771 00000000000 023542 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
from django.test import TestCase
from django.template import Context, Template
class TestBleachTemplates(TestCase):
""" Test template tags """
def test_bleaching(self):
""" Test that unsafe tags are sanitised """
context = Context(
{'some_unsafe_content': ''},
)
template_to_render = Template(
'{% load bleach_tags %}'
'{{ some_unsafe_content|bleach }}'
)
rendered_template = template_to_render.render(context)
self.assertInHTML(
'<script>alert("Hello World!")</script>',
rendered_template
)
def test_bleaching_none(self):
""" Test that None is handled properly as an input """
context = Context(
{'none_value': None}
)
template_to_render = Template(
'{% load bleach_tags %}'
'{{ none_value|bleach }}'
)
rendered_template = template_to_render.render(context)
self.assertEqual(
'None',
rendered_template
)
def test_bleaching_tags(self):
""" Test provided tags are kept """
context = Context(
{'some_unsafe_content': ''}
)
template_to_render = Template(
'{% load bleach_tags %}'
'{{ some_unsafe_content|bleach:"script" }}'
)
rendered_template = template_to_render.render(context)
self.assertInHTML(
'', rendered_template
)
def test_linkify(self):
""" Test bleach linkify """
url = 'www.google.com'
context = Context({'link_this': url})
template_to_render = Template(
'{% load bleach_tags %}'
'{{ link_this|bleach_linkify|safe }}'
)
rendered_template = template_to_render.render(context)
self.assertInHTML(
'{0}'.format(url),
rendered_template
)
def test_linkify_none(self):
""" Test bleach linkify with None as an input """
context = Context({'none_value': None})
template_to_render = Template(
'{% load bleach_tags %}'
'{{ none_value|bleach_linkify }}'
)
rendered_template = template_to_render.render(context)
self.assertEqual(
'None',
rendered_template,
)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1626701887.0
django-bleach-0.9.0/django_bleach/utils.py 0000644 0000765 0000024 00000001115 00000000000 017774 0 ustar 00mwalker staff # -*- coding: utf-8 -*-
from django.conf import settings
def get_bleach_default_options():
bleach_args = {}
bleach_settings = {
"BLEACH_ALLOWED_TAGS": "tags",
"BLEACH_ALLOWED_ATTRIBUTES": "attributes",
"BLEACH_ALLOWED_STYLES": "styles",
"BLEACH_STRIP_TAGS": "strip",
"BLEACH_STRIP_COMMENTS": "strip_comments",
"BLEACH_ALLOWED_PROTOCOLS": "protocols"
}
for setting, kwarg in bleach_settings.items():
if hasattr(settings, setting):
bleach_args[kwarg] = getattr(settings, setting)
return bleach_args
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1632867932.9310327
django-bleach-0.9.0/django_bleach.egg-info/ 0000755 0000765 0000024 00000000000 00000000000 017756 5 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867932.0
django-bleach-0.9.0/django_bleach.egg-info/PKG-INFO 0000644 0000765 0000024 00000017461 00000000000 021064 0 ustar 00mwalker staff Metadata-Version: 1.1
Name: django-bleach
Version: 0.9.0
Summary: Easily use bleach with Django models and templates
Home-page: https://github.com/marksweb/django-bleach
Author: Tim Heap & Mark Walker
Author-email: theshow@gmail.com
License: MIT
Description: django-bleach - Bleach and sanitise user HTML
=============================================
.. image:: https://readthedocs.org/projects/django-bleach/badge/?version=latest
:target: https://django-bleach.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: http://img.shields.io/pypi/v/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: Latest Version
.. image:: http://img.shields.io/pypi/l/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: License
|
.. image:: https://codecov.io/gh/marksweb/django-bleach/branch/master/graph/badge.svg
:target: https://codecov.io/gh/marksweb/django-bleach
.. image:: https://api.codacy.com/project/badge/Grade/c34f923ab0a84a6f96728866c749d511
:alt: Codacy Badge
:target: https://app.codacy.com/app/marksweb/django-bleach?utm_source=github.com&utm_medium=referral&utm_content=marksweb/django-bleach&utm_campaign=Badge_Grade_Dashboard
.. image:: http://img.shields.io/pypi/dm/django-bleach.svg?style=flat-square
:target: https://pypi.python.org/pypi/django-bleach/
:alt: Downloads
|
Bleach_ is a Python module that takes any HTML input, and returns
valid, sanitised HTML that contains only an allowed subset of HTML tags,
attributes and styles. ``django-bleach`` is a Django app that makes using
``bleach`` extremely easy.
`Read the documentation here`_.
Setup
-----
1. Install ``django-bleach`` via ``pip``::
pip install django-bleach
2. Add ``django-bleach`` to your ``INSTALLED_APPS``::
INSTALLED_APPS = [
# ...
'django_bleach',
# ...
]
3. Select some sensible defaults for the allowed tags, attributes and styles;
and the behaviour when unknown tags are encountered. Each of these are
optional, and default to using the ``bleach`` defaults. See the
`bleach documentation`_::
# Which HTML tags are allowed
BLEACH_ALLOWED_TAGS = ['p', 'b', 'i', 'u', 'em', 'strong', 'a']
# Which HTML attributes are allowed
BLEACH_ALLOWED_ATTRIBUTES = ['href', 'title', 'style']
# Which CSS properties are allowed in 'style' attributes (assuming
# style is an allowed attribute)
BLEACH_ALLOWED_STYLES = [
'font-family', 'font-weight', 'text-decoration', 'font-variant']
# Strip unknown tags if True, replace with HTML escaped characters if
# False
BLEACH_STRIP_TAGS = True
# Strip comments, or leave them in.
BLEACH_STRIP_COMMENTS = False
4. Select the default widget for bleach fields. This defaults to
``django.forms.Textarea``, but you will probably want to replace it with a
WYSIWYG editor, or something similar::
# Use the CKEditorWidget for bleached HTML fields
BLEACH_DEFAULT_WIDGET = 'wysiwyg.widgets.WysiwygWidget'
I use `django-ckeditor`_ in my projects, but what you use is up to you.
Usage
-----
In your models
**************
``django-bleach`` provides three ways of creating bleached output. The simplest
way of including user-editable HTML content that is automatically sanitised is
by using the ``BleachField`` model field::
# in app/models.py
from django import models
from django_bleach.models import BleachField
class Post(models.Model):
title = models.CharField()
content = BleachField()
# ...
``BleachField`` takes the following arguments, to customise the output of
``bleach``. See the `bleach documentation`_ for their use:
* ``allowed_tags``
* ``allowed_attributes``
* ``allowed_styles``
* ``strip_tags``
* ``strip_comments``
In addition to the ``bleach``-specific arguments, the ``BleachField`` model field
accepts all of the normal field attributes. Behind the scenes, it is a
``TextField``, and accepts all the same arguments as the default ``TextField`` does.
The ``BleachField`` model field sanitises its value before it is saved to the
database and is marked safe so it can be immediately rendered in a template
without further intervention.
In model forms, ``BleachField`` model field are represented with the
``BleachField`` form field by default.
In your forms
*************
A ``BleachField`` form field is provided. This field sanitises HTML input from
the user, and presents safe, clean HTML to your Django application and the
returned value is marked safe for immediate rendering.
In your templates
*****************
If you have a piece of content from somewhere that needs to be printed in a
template, you can use the ``bleach`` filter::
{% load bleach_tags %}
{{ some_unsafe_content|bleach }}
If filter has no arguments it uses default settings defined in your
application settings. You can override allowed tags by specifying them
as a parameter to the filter::
{{ some_unsafe_content|bleach:"p,span" }}
There is also ``bleach_linkify`` which uses the linkify_ function of bleach
which converts URL-like strings in an HTML fragment to links
This function converts strings that look like URLs, domain names and email
addresses in text that may be an HTML fragment to links, while preserving:
1. links already in the string
2. urls found in attributes
3. email addresses
.. _bleach: https://github.com/mozilla/bleach
.. _Read the documentation here: https://django-bleach.readthedocs.io/
.. _bleach documentation: https://bleach.readthedocs.io/en/latest/clean.html
.. _django-ckeditor: https://github.com/shaunsephton/django-ckeditor
.. _linkify: https://bleach.readthedocs.io/en/latest/linkify.html?highlight=linkify#bleach.linkify "linkify"
Platform: UNKNOWN
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Framework :: Django :: 2.2
Classifier: Framework :: Django :: 3.0
Classifier: Framework :: Django :: 3.1
Classifier: Framework :: Django :: 3.2
Classifier: Framework :: Django :: 4.0
Classifier: Development Status :: 5 - Production/Stable
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867932.0
django-bleach-0.9.0/django_bleach.egg-info/SOURCES.txt 0000644 0000765 0000024 00000001304 00000000000 021640 0 ustar 00mwalker staff CHANGELOG.md
LICENSE
MANIFEST.in
README.rst
setup.cfg
setup.py
django_bleach/__init__.py
django_bleach/forms.py
django_bleach/models.py
django_bleach/utils.py
django_bleach.egg-info/PKG-INFO
django_bleach.egg-info/SOURCES.txt
django_bleach.egg-info/dependency_links.txt
django_bleach.egg-info/requires.txt
django_bleach.egg-info/top_level.txt
django_bleach/templatetags/__init__.py
django_bleach/templatetags/bleach_tags.py
django_bleach/tests/__init__.py
django_bleach/tests/test_forms.py
django_bleach/tests/test_modelformfield.py
django_bleach/tests/test_models.py
django_bleach/tests/test_settings.py
django_bleach/tests/test_templatetags.py
docs/index.rst
docs/settings.rst
docs/setup.rst
docs/usage.rst ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867932.0
django-bleach-0.9.0/django_bleach.egg-info/dependency_links.txt 0000644 0000765 0000024 00000000001 00000000000 024024 0 ustar 00mwalker staff
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867932.0
django-bleach-0.9.0/django_bleach.egg-info/requires.txt 0000644 0000765 0000024 00000000033 00000000000 022352 0 ustar 00mwalker staff bleach>=1.5.0
Django>=1.11
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867932.0
django-bleach-0.9.0/django_bleach.egg-info/top_level.txt 0000644 0000765 0000024 00000000016 00000000000 022505 0 ustar 00mwalker staff django_bleach
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1632867932.9957907
django-bleach-0.9.0/docs/ 0000755 0000765 0000024 00000000000 00000000000 014454 5 ustar 00mwalker staff ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1549068449.0
django-bleach-0.9.0/docs/index.rst 0000644 0000765 0000024 00000001106 00000000000 016313 0 ustar 00mwalker staff .. django-bleach documentation master file, created by
sphinx-quickstart on Tue Jun 19 10:24:12 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
``django-bleach``
=======================
``bleach`` is a Python module that takes any HTML input, and returns valid,
sanitised HTML that contains only an allowed subset of HTML tags, attributes
and styles. ``django-bleach`` is a Django app that makes using bleach extremely
easy.
Contents:
.. toctree::
:maxdepth: 2
setup
usage
settings
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1549069472.0
django-bleach-0.9.0/docs/settings.rst 0000644 0000765 0000024 00000004624 00000000000 017054 0 ustar 00mwalker staff .. _settings:
========
Settings
========
Configuring ``bleach``
======================
You can configure how ``bleach`` acts for your whole project using the
following settings. These settings map directly to the ``bleach`` parameters of
the same name, so see the ``bleach`` `documentation` for more information. Each
of these have a sensible default set by ``bleach``, and each of these are
completely optional::
# Which HTML tags are allowed
BLEACH_ALLOWED_TAGS = ['p', 'b', 'i', 'u', 'em', 'strong', 'a']
# Which HTML attributes are allowed
BLEACH_ALLOWED_ATTRIBUTES = ['href', 'title', 'style']
# Which CSS properties are allowed in 'style' attributes (assuming style is
# an allowed attribute)
BLEACH_ALLOWED_STYLES = [
'font-family', 'font-weight', 'text-decoration', 'font-variant'
]
# Which protocols (and pseudo-protocols) are allowed in 'src' attributes
# (assuming src is an allowed attribute)
BLEACH_ALLOWED_PROTOCOLS = [
'http', 'https', 'data'
]
# Strip unknown tags if True, replace with HTML escaped characters if False
BLEACH_STRIP_TAGS = True
# Strip HTML comments, or leave them in.
BLEACH_STRIP_COMMENTS = False
You can override each of these for individual ``BleachField`` form and model
fields if you need to. Simply pass in one of the following settings you want to
override as a named parameter to the ``BleachField``::
* ``allowed_tags``
* ``allowed_attributes``
* ``allowed_styles``
* ``allowed_protocols``
* ``strip_tags``
* ``strip_comments``
An example, where blog posts should be allowed to contain images and headings::
# in app/models.py
from django import models
from django_bleach.models import BleachField
class Post(models.Model):
title = models.CharField()
content = BleachField(allowed_tags=[
'p', 'b', 'i', 'u', 'em', 'strong', 'a',
'img', 'h3', 'h4', 'h5', 'h6'])
Default form widget
===================
By default, a ``BleachField`` will use a ``django.forms.Textarea`` widget. This
is obviously not great for users. You can override this to use a custom widget
in your project. You will probably want to use a WYSIWYG editor, or something
similar::
BLEACH_DEFAULT_WIDGET = 'wysiwyg.widgets.WysiwygWidget'
I use ``django-ckeditor`` in my projects, but what you use is up to you.
.. _documentation: http://bleach.readthedocs.org/en/latest/index.html
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1582721033.0
django-bleach-0.9.0/docs/setup.rst 0000644 0000765 0000024 00000001333 00000000000 016346 0 ustar 00mwalker staff =====
Setup
=====
.. _setup:
1. Get the source from the `Git repository`_ or install it from the Python
Package Index by running ``pip install django-bleach``.
2. Add ``django_bleach`` to the ``INSTALLED_APPS`` setting::
INSTALLED_APPS += (
'django_bleach',
)
3. Configure ``django_bleach``. It comes with some sensible defaults, but you
will probably want to tweak the settings for your application. See the
:ref:`settings` page for more information
3. Add a ``django_bleach.models.BleachField`` to a model, a
``django_bleach.forms.BleachField`` to a form, or use the ``bleach``
template filter in your templates.
.. _Git repository: http://bitbucket.org/ionata/django-bleach/
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632856487.0
django-bleach-0.9.0/docs/usage.rst 0000644 0000765 0000024 00000005465 00000000000 016324 0 ustar 00mwalker staff .. _usage:
=====
Usage
=====
.. _models:
In your models
==============
``django-bleach`` provides three ways of creating bleached output. The simplest
way of including user-editable HTML content that is automatically sanitised is
by using the BleachField model field::
# in app/models.py
from django import models
from django_bleach.models import BleachField
class Post(models.Model):
title = models.CharField()
content = BleachField()
``BleachField`` takes the following arguments, to customise the output of
``bleach``.
See the bleach documentation for their use:
* ``allowed_tags``
* ``allowed_attributes``
* ``allowed_styles``
* ``allowed_protocols``
* ``strip_tags``
* ``strip_comments``
In addition to the bleach-specific arguments, the ``BleachField`` model field
accepts all of the normal field attributes. Behind the scenes, it is a
``TextField``, and accepts all the same arguments as ``TextField``.
The ``BleachField`` model field sanitises its value before it is saved to the
database and is marked safe so it can be immediately rendered in a template
without further intervention.
In model forms, ``BleachField`` model field are represented with the
``BleachField`` form field by default.
.. _forms:
In your forms
=============
A ``BleachField`` form field is provided. This field sanitises HTML input from
the user, and presents safe, clean HTML to your Django application and the
returned value is marked safe for immediate rendering.
Usually you will want to use a ``BleachField`` model field, as opposed to the
form field, but if you want, you can just use the form field. One possible use
case for this set up is to force user input to be bleached, but allow
administrators to add any content they like via another form (e.g. the admin
site)::
# in app/forms.py
from django import forms
from django_bleach.forms import BleachField
from app.models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
content = BleachField()
The ``BleachField`` form field takes exactly the same arguments as the
``BleachField`` model field above.
.. _templates:
In your templates
=================
If you have a piece of content from somewhere that needs to be printed in a
template, you can use the ``bleach`` filter::
{% load bleach_tags %}
{{ some_unsafe_content|bleach }}
It uses the ``ALLOWED_TAGS`` setting in your application, or optionally,
``bleach`` can pass tags::
{% load bleach_tags %}
{{ some_unsafe_content|bleach:"p,span" }}
If you have content which doesn't contain HTML, but contains links or email
addresses, you can also use the ``bleach_linkify`` filter to convert
content to links::
{% load bleach_tags %}
{{ some_safe_content|bleach_linkify }}
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1632867932.9995627
django-bleach-0.9.0/setup.cfg 0000644 0000765 0000024 00000001234 00000000000 015345 0 ustar 00mwalker staff [bdist_wheel]
universal = 1
[flake8]
accept-encodings = utf-8,utf-16
max-line-length = 119
exclude =
*.egg-info,
.git,
.settings,
.tox,
build,
dist,
docs,
requirements,
tmp,
*migrations*,
tests,
data
ignore =
E800,
W503,
C812,
C813,
C815,
C818,
C819,
C408
[isort]
line_length = 88
multi_line_output = 3
lines_after_imports = 2
combine_as_imports = true
include_trailing_comma = true
balanced_wrapping = true
skip = manage.py, migrations, .tox
known_standard_library = mock
known_django = django
known_first_party = django_bleach
sections = FUTURE, STDLIB, DJANGO, THIRDPARTY, FIRSTPARTY, LIB, LOCALFOLDER
[egg_info]
tag_build =
tag_date = 0
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1632867565.0
django-bleach-0.9.0/setup.py 0000755 0000765 0000024 00000006764 00000000000 015256 0 ustar 00mwalker staff #!/usr/bin/env python
import codecs
import os
import re
import sys
from setuptools import setup, find_packages
from setuptools.command.test import test as test_command
try:
from sphinx.setup_command import BuildDoc
except ImportError:
BuildDoc = None
class Tox(test_command):
user_options = [('tox-args=', 'a', "Arguments to pass to tox")]
def initialize_options(self):
test_command.initialize_options(self)
self.tox_args = None
def finalize_options(self):
test_command.finalize_options(self)
self.test_args = []
self.test_suite = True
def run_tests(self):
# import here, cause outside the eggs aren't loaded
import tox
import shlex
args = self.tox_args
if args:
args = shlex.split(self.tox_args)
errno = tox.cmdline(args=args)
sys.exit(errno)
def read(*parts):
file_path = os.path.join(os.path.dirname(__file__), *parts)
return codecs.open(file_path, encoding='utf-8').read()
def find_variable(variable, *parts):
version_file = read(*parts)
version_match = re.search(
r"^{0} = ['\"]([^'\"]*)['\"]".format(variable), version_file, re.M
)
if version_match:
return str(version_match.group(1))
raise RuntimeError("Unable to find version string.")
name = 'django-bleach'
release = find_variable('__version__', 'django_bleach', '__init__.py')
version = release.rstrip('.')
if sys.argv[-1] == 'build':
os.system('python setup.py sdist bdist_wheel')
sys.exit()
if sys.argv[-1] == 'release':
os.system('twine upload -r django-bleach --skip-existing dist/*')
sys.exit()
if sys.argv[-1] == 'tag':
print("Tagging the version on github:")
os.system("git tag -a %s -m 'version %s'" % (version, version))
os.system("git push --tags")
sys.exit()
setup(
name=name,
version=version,
description='Easily use bleach with Django models and templates',
long_description=read('README.rst'),
author=find_variable('__author__', 'django_bleach', '__init__.py'),
author_email='theshow@gmail.com',
url='https://github.com/marksweb/django-bleach',
license='MIT',
packages=find_packages(exclude=('testproject*',)),
install_requires=[
'bleach>=1.5.0',
'Django>=1.11',
],
tests_require=[
'bleach>=1.5.0',
'mock',
'sphinx',
'tox'
],
cmdclass={
'build_sphinx': BuildDoc,
'test': Tox
},
command_options={
'build_sphinx': {
'project': ('setup.py', name),
'version': ('setup.py', version),
'release': ('setup.py', release),
'source_dir': ('setup.py', 'docs'),
'build_dir': ('setup.py', './docs/_build')
}
},
package_data={},
classifiers=[
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Framework :: Django :: 3.1',
'Framework :: Django :: 3.2',
'Framework :: Django :: 4.0',
'Development Status :: 5 - Production/Stable',
],
)