Source code for mezzanine.core.forms

from __future__ import unicode_literals
from future.builtins import str

from datetime import datetime
from uuid import uuid4

from django import forms
try:
    from django.forms.widgets import SelectDateWidget
except ImportError:
    # Django 1.8
    from django.forms.extras.widgets import SelectDateWidget

from django.forms.utils import to_current_timezone
from django.utils.safestring import mark_safe

from mezzanine.conf import settings
from mezzanine.utils.static import static_lazy as static


[docs]class Html5Mixin(object): """ Mixin for form classes. Adds HTML5 features to forms for client side validation by the browser, like a "required" attribute and "email" and "url" input types. """ def __init__(self, *args, **kwargs): super(Html5Mixin, self).__init__(*args, **kwargs) if hasattr(self, "fields"): first_field = None for name, field in self.fields.items(): # Autofocus first non-hidden field if not first_field and not field.widget.is_hidden: first_field = field first_field.widget.attrs["autofocus"] = "" if settings.FORMS_USE_HTML5: if isinstance(field, forms.EmailField): self.fields[name].widget.input_type = "email" elif isinstance(field, forms.URLField): self.fields[name].widget.input_type = "url" if field.required: self.fields[name].widget.attrs["required"] = ""
[docs]class TinyMceWidget(forms.Textarea): """ Setup the JS files and targetting CSS class for a textarea to use TinyMCE. """ class Media: js = [static("mezzanine/tinymce/tinymce.min.js"), static("mezzanine/tinymce/jquery.tinymce.min.js"), static(settings.TINYMCE_SETUP_JS)] css = {'all': [static("mezzanine/tinymce/tinymce.css")]} def __init__(self, *args, **kwargs): super(TinyMceWidget, self).__init__(*args, **kwargs) self.attrs["class"] = "mceEditor"
[docs]class OrderWidget(forms.HiddenInput): """ Add up and down arrows for ordering controls next to a hidden form field. """ @property def is_hidden(self): return False def render(self, *args, **kwargs): rendered = super(OrderWidget, self).render(*args, **kwargs) arrows = ["<img src='%sadmin/img/admin/arrow-%s.gif' />" % (settings.STATIC_URL, arrow) for arrow in ("up", "down")] arrows = "<span class='ordering'>%s</span>" % "".join(arrows) return rendered + mark_safe(arrows)
[docs]class DynamicInlineAdminForm(forms.ModelForm): """ Form for ``DynamicInlineAdmin`` that can be collapsed and sorted with drag and drop using ``OrderWidget``. """ class Media: js = [static("mezzanine/js/%s" % settings.JQUERY_UI_FILENAME), static("mezzanine/js/admin/dynamic_inline.js")]
[docs]class SplitSelectDateTimeWidget(forms.SplitDateTimeWidget): """ Combines Django's ``SelectDateTimeWidget`` and ``SelectDateWidget``. """ def __init__(self, attrs=None, date_format=None, time_format=None): date_widget = SelectDateWidget(attrs=attrs) time_widget = forms.TimeInput(attrs=attrs, format=time_format) forms.MultiWidget.__init__(self, (date_widget, time_widget), attrs) def decompress(self, value): if isinstance(value, str): return value.split(" ", 1) elif isinstance(value, datetime): value = to_current_timezone(value) return [value.date(), value.time().replace(microsecond=0)] return [None, None] def value_from_datadict(self, data, files, name): return " ".join([x or "" for x in super(SplitSelectDateTimeWidget, self).value_from_datadict(data, files, name)])
[docs]class CheckboxSelectMultiple(forms.CheckboxSelectMultiple): """ Wraps render with a CSS class for styling. """ dont_use_model_field_default_for_empty_data = True def render(self, *args, **kwargs): rendered = super(CheckboxSelectMultiple, self).render(*args, **kwargs) return mark_safe("<span class='multicheckbox'>%s</span>" % rendered)
[docs]def get_edit_form(obj, field_names, data=None, files=None): """ Returns the in-line editing form for editing a single model field. """ # Map these form fields to their types defined in the forms app so # we can make use of their custom widgets. from mezzanine.forms import fields widget_overrides = { forms.DateField: fields.DATE, forms.DateTimeField: fields.DATE_TIME, forms.EmailField: fields.EMAIL, } class EditForm(forms.ModelForm): """ In-line editing form for editing a single model field. """ app = forms.CharField(widget=forms.HiddenInput) model = forms.CharField(widget=forms.HiddenInput) id = forms.CharField(widget=forms.HiddenInput) fields = forms.CharField(widget=forms.HiddenInput) class Meta: model = obj.__class__ fields = field_names.split(",") def __init__(self, *args, **kwargs): super(EditForm, self).__init__(*args, **kwargs) self.uuid = str(uuid4()) for f in self.fields.keys(): field_class = self.fields[f].__class__ try: widget = fields.WIDGETS[widget_overrides[field_class]] except KeyError: pass else: self.fields[f].widget = widget() css_class = self.fields[f].widget.attrs.get("class", "") css_class += " " + field_class.__name__.lower() self.fields[f].widget.attrs["class"] = css_class self.fields[f].widget.attrs["id"] = "%s-%s" % (f, self.uuid) if settings.FORMS_USE_HTML5 and self.fields[f].required: self.fields[f].widget.attrs["required"] = "" initial = {"app": obj._meta.app_label, "id": obj.id, "fields": field_names, "model": obj._meta.object_name.lower()} return EditForm(instance=obj, initial=initial, data=data, files=files)