Changeset - 529cb3e7db9b
[Not reviewed]
default
0 2 1
Branko Majic (branko) - 11 years ago 2013-07-24 21:16:13
branko@majic.rs
CONNT-13: Moved the CSS styling and text input placeholder setting into auxiliary form mixin clases. Update existing forms and tests.
3 files changed with 189 insertions and 59 deletions:
0 comments (0 inline, 0 general)
conntrackt/forms.py
Show inline comments
 
# Django imports.
 
from django.forms import ModelForm
 
from django.forms.models import inlineformset_factory
 

	
 
# Application imports.
 
from .models import Entity, Interface, Communication
 

	
 

	
 
class EntityForm(ModelForm):
 
class WidgetCSSClassFormMixin(object):
 
    """
 
    Helper form mixin that can be used for applying additional custom CSS
 
    classes to form field widgets.
 

	
 
    The mixin accepts the following class options:
 

	
 
        widget_css_classes - Dictionary describing which additional CSS classes
 
        should be applied to which form widget. Dictinoary keys should be equal
 
        to form widget names, while the value should be a string containing the
 
        extra CSS classes that should be applied to it. In order to apply the
 
        CSS classes to every widget of the form, use the key "ALL"
 
    """
 

	
 
    def __init__(self, *args, **kwargs):
 
        """
 
        Assigns the custom CSS classes form widgets, as configured by the
 
        widget_css_classes property.
 
        """
 

	
 
        super(WidgetCSSClassFormMixin, self).__init__(*args, **kwargs)
 

	
 
        for field_name, css_class in self.widget_css_classes.iteritems():
 
            if field_name == "ALL":
 
                for field in self.fields.values():
 
                    if "class" in field.widget.attrs:
 
                        field.widget.attrs["class"] += " " + css_class
 
                    else:
 
                        field.widget.attrs["class"] = css_class
 
            else:
 
                field = self.fields[field_name]
 
                if "class" in field.widget.attrs:
 
                    field.widget.attrs["class"] += " " + css_class
 
                else:
 
                    field.widget.attrs["class"] = css_class
 

	
 

	
 
class PlaceholderFormMixin(object):
 
    """
 
    Helper form mixin that can be used to set-up placeholders for text widgets.
 

	
 
    The mixin accepts the following class options:
 

	
 
        widget_placeholders - Dictionary describing which placeholders should be
 
        applied to which widgets. Keys should be equal to form widget names,
 
        while the values should be the strings that should be set as
 
        placeholders.
 
    """
 

	
 
    def __init__(self, *args, **kwargs):
 
        """
 
        Assigns the placeholders to text form widgets, as configured by the
 
        widget_placeholders property.
 
        """
 

	
 
        super(PlaceholderFormMixin, self).__init__(*args, **kwargs)
 

	
 
        for field_name, placeholder in self.widget_placeholders.iteritems():
 
            self.fields[field_name].widget.attrs["placeholder"] = placeholder
 

	
 

	
 
class EntityForm(WidgetCSSClassFormMixin, PlaceholderFormMixin, ModelForm):
 
    """
 
    Implements a custom model form for entities with some styling changes.
 
    """
 
@@ -14,24 +74,12 @@ class EntityForm(ModelForm):
 
    class Meta:
 
        model = Entity
 

	
 
    def __init__(self, *args, **kwargs):
 
        """
 
        Initialises the form instance. Sets-up some bootstrap CSS classes for
 
        widgets.
 
        """
 

	
 
        super(EntityForm, self).__init__(*args, **kwargs)
 

	
 
        # Update the widgets to be wider.
 
        for field_name, field in self.fields.iteritems():
 
            field.widget.attrs["class"] = "span6"
 

	
 
        # Set-up some placeholders.
 
        self.fields["name"].widget.attrs["placeholder"] = "Entity name"
 
        self.fields["description"].widget.attrs["placeholder"] = "Entity description"
 
    widget_placeholders = {"name": "Entity name",
 
                           "description": "Entity description"}
 
    widget_css_classes = {"ALL": "span6"}
 

	
 

	
 
class InterfaceForm(ModelForm):
 
class InterfaceForm(WidgetCSSClassFormMixin, PlaceholderFormMixin, ModelForm):
 
    """
 
    Implements a custom model form for interfaces with some styling changes.
 
    """
 
@@ -39,26 +87,15 @@ class InterfaceForm(ModelForm):
 
    class Meta:
 
        model = Interface
 

	
 
    def __init__(self, *args, **kwargs):
 
        """
 
        Initialises the form instance. Sets-up some bootstrap CSS classes for
 
        widgets.
 
        """
 

	
 
        super(InterfaceForm, self).__init__(*args, **kwargs)
 
    widget_placeholders = {"name": "Interface name",
 
                           "description": "Interface description",
 
                           "address": "IP address of interface",
 
                           "netmask": "IP address netmask"}
 

	
 
        # Update the widgets to be wider.
 
        for field_name, field in self.fields.iteritems():
 
            field.widget.attrs["class"] = "span6"
 

	
 
        # Set-up some placeholders.
 
        self.fields["name"].widget.attrs["placeholder"] = "Interface name"
 
        self.fields["description"].widget.attrs["placeholder"] = "Interface description"
 
        self.fields["address"].widget.attrs["placeholder"] = "IP address of interface"
 
        self.fields["netmask"].widget.attrs["placeholder"] = "IP address netmask"
 
    widget_css_classes = {"ALL": "span6"}
 

	
 

	
 
class CommunicationForm(ModelForm):
 
class CommunicationForm(WidgetCSSClassFormMixin, PlaceholderFormMixin, ModelForm):
 
    """
 
    Implements a custom model form for communications with some styling changes.
 
    """
 
@@ -66,18 +103,7 @@ class CommunicationForm(ModelForm):
 
    class Meta:
 
        model = Communication
 

	
 
    def __init__(self, *args, **kwargs):
 
        """
 
        Initialises the form instance. Sets-up some bootstrap CSS classes for
 
        widgets.
 
        """
 

	
 
        super(CommunicationForm, self).__init__(*args, **kwargs)
 
    widget_placeholders = {"port": "Port used for communication",
 
                           "description": "Communication description"}
 

	
 
        # Update the widgets to be wider.
 
        for field_name, field in self.fields.iteritems():
 
            field.widget.attrs["class"] = "span6"
 

	
 
        # Set-up some placeholders.
 
        self.fields["port"].widget.attrs["placeholder"] = "Port used for communication"
 
        self.fields["description"].widget.attrs["placeholder"] = "Communication description"
 
    widget_css_classes = {"ALL": "span6"}
conntrackt/tests/forms.py
Show inline comments
 
new file 100644
 
# Django imports
 
from django import forms
 

	
 
# Application imports.
 
from conntrackt.forms import WidgetCSSClassFormMixin, PlaceholderFormMixin
 

	
 

	
 
class FormWithWidgetCSSClassFormMixin(WidgetCSSClassFormMixin, forms.Form):
 
    """
 
    Helper form for testing the WidgetCSSClassFormMixin.
 
    """
 

	
 
    field1 = forms.CharField()
 
    field2 = forms.CharField()
 

	
 

	
 
class FormWithPlaceholderFormMixin(PlaceholderFormMixin, forms.Form):
 

	
 
    field1 = forms.CharField()
 
    field2 = forms.CharField()
conntrackt/tests/test_forms.py
Show inline comments
 
# Django imports.
 
from django.test import TestCase
 

	
 
# Python third-party library imports.
 
import mock
 

	
 
# Application imports.
 
from conntrackt.forms import EntityForm
 
from conntrackt.forms import WidgetCSSClassFormMixin, PlaceholderFormMixin
 
from conntrackt.forms import EntityForm, InterfaceForm, CommunicationForm
 

	
 
# Test imports.
 
from .forms import FormWithWidgetCSSClassFormMixin, FormWithPlaceholderFormMixin
 

	
 

	
 
class EntityFormTest(TestCase):
 
class WidgetCSSClassFormMixinTest(TestCase):
 
    """
 
    Tests for the custom Entity model form.
 
    Tests the form mixin.
 
    """
 

	
 
    def test_styling(self):
 
    def test_apply_to_all(self):
 
        """
 
        Test if CSS class is appled to all form field widgets.
 
        """
 

	
 
        # Set-up the form.
 
        form_class = FormWithWidgetCSSClassFormMixin
 
        form_class.widget_css_classes = {"ALL": "test"}
 
        form = form_class()
 

	
 
        self.assertEqual(form.fields["field1"].widget.attrs["class"], "test")
 
        self.assertEqual(form.fields["field2"].widget.attrs["class"], "test")
 

	
 
    def test_apply_to_single(self):
 
        """
 
        Test that the form styling is set-up correctly.
 
        Test if CSS class is appled to a single field widget.
 
        """
 

	
 
        # Set-up the form.
 
        form_class = FormWithWidgetCSSClassFormMixin
 
        form_class.widget_css_classes = {"field2": "test"}
 
        form = form_class()
 

	
 
        self.assertEqual(form.fields["field1"].widget.attrs.get("class", None), None)
 
        self.assertEqual(form.fields["field2"].widget.attrs["class"], "test")
 

	
 
    def test_apply_multiple(self):
 
        """
 
        Tests if different class is applied to multiple form field widgets.
 
        """
 

	
 
        form = EntityForm()
 
        # Set-up the form.
 
        form_class = FormWithWidgetCSSClassFormMixin
 
        form_class.widget_css_classes = {"field1": "f1",
 
                                         "field2": "f2"}
 
        form = form_class()
 

	
 
        self.assertEqual(form.fields["field1"].widget.attrs["class"], "f1")
 
        self.assertEqual(form.fields["field2"].widget.attrs["class"], "f2")
 

	
 
    def test_apply_to_all_additional(self):
 
        """
 
        Tests if all widgets get the same CSS class in addition to induvidual
 
        ones.
 
        """
 

	
 
        # Set-up the form.
 
        form_class = FormWithWidgetCSSClassFormMixin
 
        form_class.widget_css_classes = {"field1": "f1",
 
                                         "field2": "f2",
 
                                         "ALL": "all"}
 
        form = form_class()
 

	
 
        self.assertEqual(sorted(["f1", "all"]), sorted(form.fields["field1"].widget.attrs["class"].split(" ")))
 
        self.assertEqual(sorted(["f2", "all"]), sorted(form.fields["field2"].widget.attrs["class"].split(" ")))
 

	
 

	
 
        self.assertIn("span6", form.fields["name"].widget.attrs["class"])
 
        self.assertIn("span6", form.fields["description"].widget.attrs["class"])
 
        self.assertIn("span6", form.fields["project"].widget.attrs["class"])
 
        self.assertIn("span6", form.fields["location"].widget.attrs["class"])
 
class PlaceholderFormMixinTest(TestCase):
 
    """
 
    Tests the form mixin.
 
    """
 

	
 
    def test_apply_one(self):
 
        """
 
        Test if a single placeholder is applied to a form field widget.
 
        """
 

	
 
        # Set-up the form.
 
        form_class = FormWithPlaceholderFormMixin
 
        form_class.widget_placeholders = {"field1": "place1"}
 
        form = form_class()
 

	
 
        self.assertEqual(form.fields["field1"].widget.attrs["placeholder"], "place1")
 
        self.assertEqual(form.fields["field2"].widget.attrs.get("placeholder", None), None)
 

	
 
    def test_apply_multiple(self):
 
        """
 
        Test if multiple placeholders are applied to form field widgets.
 
        """
 

	
 
        # Set-up the form.
 
        form_class = FormWithPlaceholderFormMixin
 
        form_class.widget_placeholders = {"field1": "place1",
 
                                   "field2": "place2"}
 
        form = form_class()
 

	
 
        self.assertEqual(form.fields["field1"].widget.attrs["placeholder"], "place1")
 
        self.assertEqual(form.fields["field2"].widget.attrs["placeholder"], "place2")
0 comments (0 inline, 0 general)