svv/forms.py
author Tero Marttila <terom@fixme.fi>
Fri, 21 Jan 2011 04:44:30 +0200
changeset 61 ce1d012d02fe
parent 48 06fa83c8c0bb
permissions -rw-r--r--
html: amend
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     1
"""
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     2
    Form rendering and handling
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     3
"""
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     4
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
from svv.html import tags
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
from svv import database as db
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     8
import collections
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     9
import datetime
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    10
import logging
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    11
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    12
try :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    13
    # Python2.6 stdlib
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    14
    import json
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    15
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    16
except ImportError :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    17
    # simplejson, API should be similar
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    18
    import simplejson as json
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    19
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    20
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    21
log = logging.getLogger('svv.forms')
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    22
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    23
class FormError (Exception) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    24
    """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    25
        A user-level error in a form field
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    26
    """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    27
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    28
    def __init__ (self, field, value, error) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    29
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    30
                field       - name of field with error
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    31
                value       - the errenous value in the form that we recieved it
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    32
                              may be None if it was the *lack* of a value that caused the issue
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    33
                error       - descriptive text for user
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    34
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    35
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    36
        self.field = field
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    37
        self.value = value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    38
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    39
        super(FormError, self).__init__(error)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    40
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    41
class BaseForm (object) :
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
    42
    # processed POST data
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    43
    data = None
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    44
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
    45
    def __init__ (self) :
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    46
        """
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
    47
            Setup state.
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
    48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
    49
            Note that a Form is stateful, and should only be used for one form transaction.
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    50
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    51
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    52
        # accumulated errors
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    53
        self.errors = collections.defaultdict(list)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    54
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    55
    def defaults (self) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    56
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    57
            Update our attributes with default values
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    58
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    59
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    60
        raise NotImplementedError()
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    61
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    62
    def fail_field (self, form_error, field=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    63
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    64
            Mark the field mentioned inside the given FormError as failed.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    65
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    66
                form_error      - the FormError to store
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    67
                field           - the name of the field to store the error under, if not the same as in form_error
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    68
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    69
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    70
        field = field or form_error.field
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    71
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    72
        log.warn("Marking field %s as failed: %s", field, form_error)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    73
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    74
        self.errors[field].append(form_error)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    75
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    76
    def build_name_for_armed_input (self, name) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    77
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    78
            Return the name used for the checkbox associated with the named armed text input
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    79
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    80
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    81
        return name + '_enabled'
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    82
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    83
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    84
    def process_raw_field (self, name, default=None, required=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    85
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    86
            Process a generic incoming data field.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    87
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    88
                default         - value to return if no value was present
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    89
                required        - raise a FormError if no value present
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    90
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    91
            Returns the value as a str, or default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    92
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    93
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    94
        if name in self.data :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    95
            return self.data[name]
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    96
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    97
        elif required :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    98
            raise FormError(name, None, "Required field")
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    99
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   100
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   101
            return default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   102
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   103
    def process_text_field (self, name, default=None, required=None, strip=True) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   104
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   105
            Process a generic incoming string field.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   106
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   107
            Trims extra whitespace from around the value, unless strip=False is given.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   108
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   109
            Returns the value as unicode, or default.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   110
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   111
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   112
        value = self.process_raw_field(name, required=required)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   113
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   114
        if value is None :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   115
            return default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   116
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   117
        try :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   118
            # XXX: decode somehow, or can werkzeug handle that?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   119
            value = unicode(value)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   120
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   121
        except UnicodeDecodeError :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   122
            raise FormError(name, value, "Failed to decode Unicode characters")
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   123
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   124
        if strip :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   125
            value = value.strip()
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   126
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   127
        return value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   128
    
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   129
    def process_integer_field (self, name, default=None, required=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   130
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   131
            Process a generic incoming int field.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   132
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   133
            If the field is empty, uses the default value.
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   134
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   135
            Returns the value as int, or default.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   136
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   137
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   138
        value = self.process_raw_field(name, required=required)
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   139
        
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   140
        if not value:
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   141
            # not included in POST, or empty
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   142
            return default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   143
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   144
        try :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   145
            return int(value)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   146
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   147
        except ValueError :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   148
            raise FormError(name, value, "Must be a number")
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   149
    
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   150
    DATETIME_FORMAT = "%d.%m.%Y %H:%M"
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   151
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   152
    def process_datetime_field (self, name, default=None, required=None, format=DATETIME_FORMAT) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   153
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   154
            Process an incoming datetime field.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   155
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   156
            Returns the value as datetime, or default.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   157
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   158
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   159
        value = self.process_raw_field(name, required=required)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   160
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   161
        if value is None :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   162
            return default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   163
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   164
        try :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   165
            return datetime.datetime.strptime(value, format)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   166
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   167
        except ValueError, ex :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   168
            raise FormError(name, value, "Invalid date/time value: " + str(ex))
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   169
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   170
    def process_checkbox_field (self, name, required=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   171
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   172
            Process an incoming checkbox input's value.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   173
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   174
            Any non-empty/non-whitespace value will be accepted as True.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   175
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   176
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   177
        value = self.process_raw_field(name, required)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   178
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   179
        if not value and required :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   180
            raise FormError(name, value, "Must be checked")
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   181
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   182
        elif value and value.strip() :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   183
            # checked
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   184
            return True
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   185
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   186
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   187
            # unchecked
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   188
            return False
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   189
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   190
    def process_armed_text_field (self, name, required=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   191
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   192
            A text field that must be enabled by a checkbox before being used.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   193
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   194
            If not enabled, returns False. Otherwise, text field value, and fails if empty but required.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   195
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   196
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   197
        checkbox_name = self.build_name_for_armed_input(name)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   198
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   199
        if self.process_checkbox_field(checkbox_name) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   200
            # use input value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   201
            return self.process_text_field(name, required=required)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   202
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   203
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   204
            # not selected
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   205
            return False
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   206
    
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   207
    def process_action_field (self, name, required=None) :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   208
        """
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   209
            Given a form with multiple named submit buttons, checks if the given one was used to submit the form.
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   210
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   211
            If required, raises a FormError if the button wasn't pressed.
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   212
        """
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   213
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   214
        value = self.process_raw_field(name, required)
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   215
        
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   216
        if value and value.strip() :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   217
            # pressed
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   218
            return True
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   219
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   220
        elif required :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   221
            raise FormError(name, None, "Must be pressed")
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   222
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   223
        else :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   224
            # some other submit was hit
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   225
            return False
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   226
    
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   227
    def process_list_field (self, name, required=None, type=unicode) :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   228
        """
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   229
            Process an incoming multi-value field, returning the full list of values, converted using the given converter.
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   230
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   231
            Returns an empty list if no incoming values, and not rquired.
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   232
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   233
            XXX: doesn't strip() the values
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   234
        """
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   235
        
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   236
        if name not in self.data and required :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   237
            # fail
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   238
            raise FormError(name, None, "No values given")
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   239
        
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   240
        elif name not in self.data :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   241
            # empty/default
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   242
            return []
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   243
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   244
        else :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   245
            # type'd list of values
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   246
            # uses werkzeug's MultiDict API
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   247
            return self.data.getlist(name, type)
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   248
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   249
    def process_multifield (self, table, id, fields) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   250
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   251
            Process a set of user-given field values for an object with an unique id, and some set of additional fields.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   252
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   253
            If the id is given, look up the corresponding field values, and return those.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   254
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   255
            If any of the fields are given, either look up a matching row, or create a new one, and return its id.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   256
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   257
            Returns an (id_name, field_name, ...) N-tuple.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   258
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   259
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   260
        id_name, id_col, id_value = id
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   261
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   262
        if id_value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   263
            # look up object from db
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   264
            columns = [col for name, col, value in fields]
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   265
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   266
            sql = db.select(columns, (id_col == id_value))
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   267
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   268
            for row in self.app.query(sql) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   269
                # XXX: sanity-check row values vs our values
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   270
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   271
                # new values
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   272
                fields = tuple(
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   273
                    (name, col, row[col]) for name, col, value in fields
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   274
                )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   275
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   276
                # ok, just use the first one
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   277
                break
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   278
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   279
            else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   280
                # not found!
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   281
                raise FormError(id_name, id_value, "Item selected does not seem to exist")
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   282
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   283
            log.info("Lookup %s=%d -> %s", id_name, id_value, dict((name, value) for name, col, value in fields))
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   284
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   285
        elif any(value for name, col, value in fields) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   286
            # look up identical object from db?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   287
            sql = db.select([id_col], db.and_(*[(col == value) for name, col, value in fields]))
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   288
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   289
            for row in self.app.query(sql) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   290
                if id_value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   291
                    log.warn("Duplicate %s=%d for %s", id_name, id_value, dict((name, value) for name, col, value in fields))
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   292
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   293
                # found object's id
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   294
                id_value = row[id_col]
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   295
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   296
                log.info("Found %s -> %d", dict((name, value) for name, col, value in fields), id_value)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   297
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   298
            # create new object?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   299
            if not id_value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   300
                sql = db.insert(table).values(dict((col, value) for name, col, value in fields))
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   301
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   302
                id_value, = self.app.insert(sql)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   303
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   304
                log.info("Create %s -> %d", dict((name, value) for name, col, value in fields), id_value)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   305
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   306
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   307
            # not known
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   308
            log.debug("No %s known for order...", id_name)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   309
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   310
        # return full set of values
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   311
        return (id_value, ) + tuple(value for name, col, value in fields)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   312
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   313
    def process (self, data) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   314
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   315
            Bind ourselves to the given incoming POST data, and update our order field attributes.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   316
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   317
                data        - the submitted POST data as a MultiDict
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   318
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   319
            Returns True if all fields were processed without errors, False otherwise.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   320
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   321
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   322
        # bind
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   323
        self.data = data
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   324
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   325
        raise NotImplmentedError()
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   326
    
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   327
        return not self.errors
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   328
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   329
    def render_text_input (self, name, value=None, multiline=False, rows=10, autoscale=True) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   330
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   331
            Render HTML for a generic text field input.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   332
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   333
                name            - field name, as used for POST
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   334
                value           - default field value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   335
                multiline       - use a multi-line <textarea> instead
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   336
                rows            - number of rows for <textarea> per default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   337
                autoscale       - automatically scale the <textarea> to the number of lines of text
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   338
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   339
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   340
        if multiline :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   341
            if autoscale and value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   342
                rows = value.count('\n') * 5 / 4
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   343
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   344
            # XXX: textarea can't be self-closing for some reason?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   345
            return tags.textarea(name=name, id=name, rows=rows, _selfclosing=False, _whitespace_sensitive=True)(value)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   346
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   347
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   348
            return tags.input(type='text', name=name, id=name, value=value)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   349
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   350
    def render_select_input (self, name, options, value=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   351
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   352
            Render HTML for a generic select control.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   353
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   354
                name            - field name, as used for POST
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   355
                options         - sequence of (value, title) options. `value` may be None to omit.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   356
                value           - the selected value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   357
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   358
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   359
        return tags.select(name=name, id=name)(
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   360
            (
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   361
                tags.option(value=opt_value, selected=('selected' if opt_value == value else None))(opt_title)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   362
            ) for opt_value, opt_title in options
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   363
        )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   364
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   365
    def render_datetime_input (self, name, value=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   366
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   367
            Render HTML for a generic datetime control (using jQuery).
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   368
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   369
                name            - field name, as used for POST
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   370
                value           - selected date
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   371
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   372
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   373
        return (
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   374
            self.render_text_input(name, (value.strftime(self.DATETIME_FORMAT) if value else None)),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   375
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   376
            tags.script("$(document).ready(function () { $('#" + name + "').datetimepicker(); });"),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   377
        )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   378
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   379
    def render_checkbox_input (self, name, checked=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   380
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   381
            Render HTML for a checkbox.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   382
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   383
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   384
        return tags.input(type="checkbox", name=name, id=name, value="1",
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   385
            checked=("checked" if checked else None)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   386
        )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   387
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   388
    def render_armed_text_input (self, name, value=False, default=None) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   389
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   390
            Render HTML for a text field that must be enabled by a checkbox before being used.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   391
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   392
                value       - the three-state value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   393
                                False       - not checked, use default as value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   394
                                None        - checked, use empty value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   395
                                str         - checked, ues value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   396
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   397
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   398
        checkbox_name = self.build_name_for_armed_input(name)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   399
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   400
        if value is False :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   401
            checked = False
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   402
            value = default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   403
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   404
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   405
            checked = True
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   406
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   407
        return (
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   408
            self.render_checkbox_input(checkbox_name, checked),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   409
            self.render_text_input(name, value),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   410
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   411
            tags.script("$(document).ready(function () { $('#" + name + "').formEnabledBy($('#" + checkbox_name + "')); });")
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   412
        )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   413
36
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   414
    def render_reset_button (self, value, return_url=None) :
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   415
        """
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   416
            Render HTML for a <input type="reset"> that abandons the form and returns the user to a page when pressed.
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   417
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   418
                value                   - button title
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   419
                return_url              - (optional) URL to redirect user back to when button is pressed
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   420
        """
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   421
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   422
        return tags.input(type='reset', value=value, 
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   423
            onclick = (
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   424
                "$.redirect('" + return_url + "')"
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   425
            ) if return_url else None,
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   426
        )
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   427
    
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   428
    def render_submit_button (self, value, name=None) :
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   429
        """
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   430
            Render HTML for a <input type="submit">.
36
d7a159024912 forms: Add a reset/return button to separate-page forms
Tero Marttila <terom@fixme.fi>
parents: 34
diff changeset
   431
48
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   432
                value                   - button title
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   433
                name                    - optionally give the button a name for use with process_action_field
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   434
        """
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   435
06fa83c8c0bb items: Inventory management
Tero Marttila <terom@fixme.fi>
parents: 36
diff changeset
   436
        return tags.input(type='submit', name=name, value=value)
34
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   437
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   438
    def render_form_field (self, name, title, description, inputs) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   439
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   440
            Render the label, input control, error note and description for a single field, along with their containing <li>.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   441
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   442
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   443
        # any errors for this field?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   444
        errors = self.errors[name]
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   445
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   446
        return tags.li(class_='field' + (' failed' if errors else ''))(
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   447
            tags.label((
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   448
                title,
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   449
                tags.strong(u"(Virheellinen)") if errors else None,
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   450
            ), for_=name),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   451
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   452
            inputs,
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   453
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   454
            tags.p(description),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   455
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   456
            # possible errors
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   457
            tags.ul(class_='errors')(tags.li(error.message) for error in errors) if errors else None,
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   458
        )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   459
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   460
    def render (self, action, submit=u"Tallenna") :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   461
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   462
            Render the entire <form>, using any loaded/processed values.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   463
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   464
                action          - the target URL for the form to POST to
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   465
                submit          - label for the submit button
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   466
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   467
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   468
        raise NotImplementedError()
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   469
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   470
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   471