svv/forms.py
author Tero Marttila <terom@fixme.fi>
Fri, 07 Jan 2011 02:46:29 +0200
changeset 34 260413f89ba9
child 36 d7a159024912
permissions -rw-r--r--
forms: split off generic forms code from orders.py
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) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    42
    # any POST data we have processed, updated from process()
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
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    45
    def __init__ (self, app) :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    46
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    47
                app             - bind this form to the app state (db etc)
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    48
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    49
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    50
        self.app = app
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
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   133
            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
   134
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   135
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   136
        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
   137
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   138
        if value is None :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   139
            return default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   140
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   141
        try :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   142
            return int(value)
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
        except ValueError :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   145
            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
   146
    
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   147
    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
   148
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   149
    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
   150
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   151
            Process an incoming datetime field.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   152
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   153
            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
   154
        """
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
        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
   157
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   158
        if value is None :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   159
            return default
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
        try :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   162
            return datetime.datetime.strptime(value, format)
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
        except ValueError, ex :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   165
            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
   166
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   167
    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
   168
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   169
            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
   170
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   171
            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
   172
        """
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
        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
   175
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   176
        if not value and required :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   177
            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
   178
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   179
        elif value and value.strip() :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   180
            # checked
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   181
            return True
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   182
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   183
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   184
            # unchecked
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   185
            return False
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   186
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   187
    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
   188
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   189
            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
   190
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   191
            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
   192
        """
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
        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
   195
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   196
        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
   197
            # use input value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   198
            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
   199
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   200
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   201
            # not selected
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   202
            return False
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   203
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   204
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   205
    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
   206
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   207
            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
   208
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   209
            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
   210
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   211
            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
   212
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   213
            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
   214
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   215
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   216
        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
   217
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   218
        if id_value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   219
            # look up object from db
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   220
            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
   221
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   222
            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
   223
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   224
            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
   225
                # 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
   226
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   227
                # new values
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   228
                fields = tuple(
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   229
                    (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
   230
                )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   231
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   232
                # ok, just use the first one
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   233
                break
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   234
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   235
            else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   236
                # not found!
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   237
                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
   238
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   239
            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
   240
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   241
        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
   242
            # look up identical object from db?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   243
            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
   244
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   245
            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
   246
                if id_value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   247
                    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
   248
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   249
                # found object's id
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   250
                id_value = row[id_col]
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   251
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   252
                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
   253
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   254
            # create new object?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   255
            if not id_value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   256
                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
   257
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   258
                id_value, = self.app.insert(sql)
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
                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
   261
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   262
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   263
            # not known
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   264
            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
   265
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   266
        # return full set of values
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   267
        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
   268
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   269
    def process (self, data) :
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
            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
   272
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   273
                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
   274
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   275
            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
   276
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   277
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   278
        raise NotImplmentedError()
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   279
    
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   280
        return not self.errors
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   281
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   282
    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
   283
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   284
            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
   285
                
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   286
                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
   287
                value           - default field value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   288
                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
   289
                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
   290
                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
   291
        """
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
        if multiline :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   294
            if autoscale and value :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   295
                rows = value.count('\n') * 5 / 4
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   296
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   297
            # 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
   298
            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
   299
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   300
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   301
            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
   302
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   303
    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
   304
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   305
            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
   306
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   307
                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
   308
                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
   309
                value           - the selected value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   310
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   311
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   312
        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
   313
            (
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   314
                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
   315
            ) 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
   316
        )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   317
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   318
    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
   319
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   320
            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
   321
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   322
                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
   323
                value           - selected date
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   324
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   325
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   326
        return (
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   327
            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
   328
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   329
            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
   330
        )
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   331
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   332
    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
   333
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   334
            Render HTML for a checkbox.
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   335
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   336
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   337
        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
   338
            checked=("checked" if checked else None)
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
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   341
    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
   342
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   343
            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
   344
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   345
                value       - the three-state value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   346
                                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
   347
                                None        - checked, use empty value
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   348
                                str         - checked, ues 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
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   351
        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
   352
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   353
        if value is False :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   354
            checked = False
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   355
            value = default
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   356
        
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   357
        else :
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   358
            checked = True
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   359
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   360
        return (
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   361
            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
   362
            self.render_text_input(name, value),
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
            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
   365
        )
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
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   368
    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
   369
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   370
            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
   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
        # any errors for this field?
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   374
        errors = self.errors[name]
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
        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
   377
            tags.label((
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   378
                title,
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   379
                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
   380
            ), for_=name),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   381
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   382
            inputs,
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
            tags.p(description),
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   385
            
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   386
            # possible errors
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   387
            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
   388
        )
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
    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
   391
        """
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   392
            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
   393
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   394
                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
   395
                submit          - label for the submit button
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
        raise NotImplementedError()
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
260413f89ba9 forms: split off generic forms code from orders.py
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   401