base **** .. highlight:: python https://gitlab.com/kb/base BaseMixin ========= https://gitlab.com/kb/base/blob/master/base/view_utils.py The ``BaseMixin`` class adds the following to the template context: - ``path``: ``self.request.path`` or ``home`` if the path is ``/`` - ``today``: todays date (``datetime.today()``) - ``request_path``: ``self.request.path`` .. tip:: To add extra context we can use the ``BASE_MIXIN_CONTEXT_PLUGIN`` plugin system. For an example of this, see :ref:`apps_context_for_base_mixin` (from the ``apps`` app). Bullet (Hide) ============= If you create a form with a ``RadioSelect`` widget e.g:: send_email = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES) Then you can hide the bullets on the page by using the ``kb-hide-bullet`` style e.g:: {% include '_form.html' with form_class='kb-hide-bullet' %} Checkbox ======== We have (very nice) inline checkboxes: .. image:: ./misc/inline-checkbox.png :scale: 60 To make checkbox field and label appear on a single line add:: {% include '_form.html' with inline_checkbox=True ... %} .. tip:: Don't miss the nice formatting for Forms_ For more information, take a look at the documentation in the templates: - https://gitlab.com/kb/base/blob/master/base/templates/_form.html (``inline_checkbox``) - https://gitlab.com/kb/base/blob/master/base/templates/_form_field.html (``input_type``) Date Picker =========== .. tip:: The code for the `Zebra Datepicker`_ is included in our ``base.html`` template. Using ``RequiredFieldForm`` will automatically set date fields to use the zebra datepicker control e.g:: # forms.py from base.form_utils import RequiredFieldForm class EventForm(RequiredFieldForm): .. warning:: If your date control isn't working as a date picker, then check your form code to see if you call ``self.fields[name].widget.attrs.update({'class'...`` on the field. This will overwrite the update done by the ``__init__`` method on ``RequiredFieldForm``. File and Image Upload ===================== If you include the ``_form.html`` template and you want to upload files, then add the ``multipart`` option: .. code-block:: html {% include '_form.html' with multipart=True %} ``FileDropInput`` Widget ------------------------ To display a drag and drop file upload, set the widget for that field to ``FileDropInput``. If your form inherits from ``RequiredFieldForm`` all ``FileField`` and ``ImageField`` fields will automatically use the ``FileDropInput`` widget. The ``zone_id`` for the first field will be ``filedrop-zone`` and ``filedrop-1-zone`` for the second, ``filedrop-2-zone`` for the third etc. For example, assuming the following model is defined in your ``models.py``:: class Document(TimedCreateModifyDeleteModel): file = models.FileField(upload_to='document') preview = models.FileField(upload_to='image') description = models.CharField(max_length=256) class Meta: verbose_name = 'Document' verbose_name_plural = 'Documents' def __str__(self): return '{}: {}'.format(self.file, self.description) You can define a model form called ``DocumentForm`` as follows:: from django import forms from base.form_utils import FileDropInput from .models import Document class DocumentForm(models.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name in ('file', 'description'): self.fields[name].widget.attrs.update( {'class': 'pure-input-2-3'} ) class Meta: model = Document fields = ( 'file', 'preview', 'description', ) widgets = { 'file': FileDropInput() 'preview': FileDropInput( zone_id="filedrop-1-zone", default_text="Optional text to replace 'Drop a file ...'" click_text="Optional text to replace 'or click here...'" ) } or using ``RequiredFieldForm`` (which configures the each widget with the appropriate ``zone_id``) as follows:: from base.form_utils import RequiredFieldForm from .models import Document class DocumentForm(RequiredFieldForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name in ('file', 'preview', 'description'): self.fields[name].widget.attrs.update( {'class': 'pure-input-2-3'} ) class Meta: model = Document fields = ( 'file', 'preview', 'description', ) When creating a ``FileDropWidget`` you can optionally pass three parameters: ``zone_id`` which specifies the ``id`` of the drop area of your page (the default is ``filedrop-zone``). unless using ``RequiredFieldForm`` this must be specified for each subsequent ``FileDropWidget`` as the ``zone_id`` must be unique. ``default_text`` which specifies the text to be displayed when there is no file dropped (default is *Drop a file...*) ``click_text`` the text a button that allows choosing a file from the file system (default is *or click here*) If you're inheriting from RequiredFieldForm you can change the values for zone_id, default_text and click_text in the form's ``__init__`` using either of the following: Update the attrs member of the widget as follows:: self.fields['preview'].widget.attrs.update({ 'default_text': "Drop a preview image file...", 'click_text': "or click here to choose one" }) Or specify a new widget:: self.fields['preview'].widget = FileDropInput( zone_id="filedrop-1-zone", default_text="Drop a preview image file...", click_text="or click here to choose one" ) See the ``example_base`` app File Drop Demo for an example form with two FileFields. See the code in ``example_base/forms.py`` Using FileDropWidget on your page --------------------------------- ``filedrop.css`` defines a pure-css style appearance of a FileDropWidget for the standard zone_ids (these are ``filedrop-zone``, ``filedrop-1-zone``, ``filedrop-2-zone`` and ``filedrop-3-zone``). If your page inherits from the base app's ``base.html`` then this is already included. Otherwise include it on your page with the code:: It probably makes sense to include this above your project css file as this allows the styles to be overidden. ``filedrop.js`` initialises the filedrop zones created when a ``FileDropWidget`` is rendered for the standard zone_ids. If your template does not inherit from the base app's base.html, include this on your page with the code: .. code-block:: html Including the script at the end of the page ensures that DOM is loaded. Advanced control of ``FileDropWidget`` -------------------------------------- If you want to change the appearance of your ``FileDropWidget`` you will need to create css rules for some or all of the following selectors:: #filedrop-zone #filedrop-zone .filedrop-file-name #filedrop-zone .filedrop-click-here // please note if you have more than one FileDropWidget on your page you // will need to define additional selectors you can of course group your // selectors to get a similar appearance for each widget. If you want to use a different zone_id in your form or add more than 4 ``FileDropWidget`` to your page then in addition to creating a style as above you must also call ``dropZoneManager`` with the ``zone_id`` of each non standard ``zone_id`` as follows: .. code-block:: html This should appear below ``filezone.js`` on your page. Flash of Unstyled Content (FOUC) ================================ From `An Accessible Way to Stop Your Content From Flashing (FOUC)`_ Include our ``_fouc.html`` template: .. code-block:: html {% block content %} {% include 'base/_fouc.html' %} Add the ``stuffIDontWantToFlash`` style to any elements you want to hide on the initial render: .. code-block:: html