"""
Mix-ins for building your own forms.
"""
from django.forms import fields
from pytoolbox import module
from . import utils, widgets
_all = module.All(globals())
[docs]class ConvertEmailToTextMixin(object):
"""
Set email inputs as text to avoid the i18n issue
http://html5doctor.com/html5-forms-input-types#input-email.
"""
[docs] def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
if getattr(field.widget, 'input_type', None) == 'email':
field.widget.input_type = 'text'
[docs]class EnctypeMixin(object):
@property
def enctype(self):
return 'multipart/form-data' if self.is_multipart() else 'application/x-www-form-urlencoded'
[docs]class HelpTextToPlaceholderMixin(object):
"""
Update the widgets of the form to copy (and remove) the field's help text to the widget's
placeholder.
"""
#: Add a placeholder to the type of fields listed here.
placeholder_fields = (
fields.CharField,
fields.DateField,
fields.DateTimeField,
fields.DecimalField,
fields.EmailField,
fields.FloatField,
fields.IntegerField,
fields.RegexField,
fields.SlugField,
fields.TimeField
)
#: Remove the help text after having copied it to the placeholder.
placeholder_remove_help_text = True
[docs] def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
if field and isinstance(field, self.placeholder_fields):
self.set_placeholder(name, field)
[docs] def set_placeholder(self, name, field): # pylint:disable=unused-argument
field.widget.attrs['placeholder'] = field.help_text
if self.placeholder_remove_help_text:
field.help_text = None
[docs]class MapErrorsMixin(object):
"""
Map errors based on field name. Mandatory when the form contains a field from a model named
differently.
"""
errors_map = {}
[docs] def add_error(self, field, error):
field = self.errors_map.get(field, field)
return super().add_error(field, error)
[docs]class RequestMixin(object):
"""
Accept request as a optional (default: None) argument of the constructor and set it as an
attribute of the object.
"""
[docs] def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super().__init__(*args, **kwargs)
[docs]class CreatedByMixin(RequestMixin):
"""Set instance's created_by field to current user if the instance is just created."""
[docs] def save(self, commit=True):
if hasattr(self.instance, 'created_by_id') and not self.instance.created_by_id:
self.instance.created_by = self.request.user
return super().save(commit=commit)
[docs]class StaffOnlyFieldsMixin(RequestMixin):
"""Hide some fields if authenticated user is not a member of the staff."""
staff_only_fields = ()
[docs] def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.request or not self.request.user.is_staff:
for field in self.staff_only_fields:
self.fields.pop(field, None)
__all__ = _all.diff(globals())