Changes between Version 4 and Version 5 of CustomFormFields


Ignore:
Timestamp:
Feb 24, 2006, 5:16:50 PM (18 years ago)
Author:
Lllama
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • CustomFormFields

    v4 v5  
    3939
    40402006-02-20-16:20-ish
     41
    4142Looks like do_html2python is our friend here.  In line with the [wiki:NewAdminChanges new admin documentation] we need to make sure that do_html2python is called regardless of whether there are any errors.  In doing so we can get our list of IDs in a 'neat' manner.  The only problem?  What if we've got validation errors? Trying to convert the data fails when there are errors.  Which means we can't convert.  Which means that render doesn't get its nice list of IDs anymore.  Stumped.
     43
     442006-02-24-23:14-ish
     45
     46While watching Firefly I've come up with this:
     47
     48{{{
     49class FormPortField(formfields.TextField):
     50
     51    requires_data_list = True
     52
     53    def __init__(self, **kw):
     54        formfields.TextField.__init__(self, **kw)
     55        self.validator_list.append(self.isValidList)
     56
     57    def isValidList(self, field_data, all_data):
     58        for datum in field_data:
     59            for port in datum.split(','):
     60                if port.lower().strip() != 'icmp':
     61                    try:
     62                        no, proto = port.split(':')
     63                    except ValueError:
     64                        raise validators.ValidationError, _("Ports should be specified in the form 'number:protocol'.  E.g. '80:tcp'")
     65                    try:
     66                        if int(no) < 1 or int(no) > 65355:
     67                            raise validators.ValidationError, _("Port number must be between 1 and 65355")
     68                    except ValueError:
     69                        raise validators.ValidationError, _("Port number must be between 1 and 65355")
     70                    if proto.lower().strip() not in ['tcp', 'udp']:
     71                        raise validators.ValidationError, _("Protocol must be either 'TCP' or 'UDP'")
     72
     73    def render(self, data):
     74        if data is None:
     75            data = ''
     76        if isinstance(data, unicode):
     77            data = data.encode(DEFAULT_CHARSET)
     78        tmp = []
     79        for datum in data:
     80            try:
     81                port = ports.get_object(id__exact=int(datum))
     82                if port.number:
     83                    tmp.append("%s:%s" % (port.number, port.protocol))
     84                else:
     85                    tmp.append("%s" % (port.protocol, ))
     86            except ValueError:
     87                # By catching this error we now assume that it's invalid data entered by the user and
     88                # so should simply be returned in the 'raw'
     89                return '<input type="text" id="%s" class="v%s%s" name="%s" size="%s" value="%s" />' % \
     90                (self.get_id(), self.__class__.__name__, self.is_required and ' required' or '',
     91        data = ', '.join(tmp)
     92        return '<input type="text" id="%s" class="v%s%s" name="%s" size="%s" value="%s" />' % \
     93            (self.get_id(), self.__class__.__name__, self.is_required and ' required' or '',
     94            self.field_name, 40, escape(data))
     95
     96    def convert_post_data(self, new_data):
     97        name = self.get_member_name()
     98        if new_data.has_key(self.field_name):
     99            d = new_data.getlist(self.field_name)
     100            try:
     101                self.isValidList(d, new_data)
     102            except validators.ValidationError:
     103                return
     104            portlist=[]
     105            for datum in d:
     106                for n in datum.split(','):
     107                    n = n.strip()
     108                    if n:
     109                        if n.lower() == 'icmp':
     110                            portlist.append(ports.get_object(protocol__exact="icmp").id)
     111                        else:
     112                            port, proto = n.split(':')
     113                            port_ref = ports.get_object(number__exact=int(port), protocol__exact=proto.lower())
     114                            portlist.append(port_ref.id)
     115            new_data.setlist( name, portlist)
     116}}}
     117
     118Wow.  What a mess.  We end up validating the data three times over.  What a pain.  But it works.
Back to Top