Django : presenting a form very different from the model and with multiple field values in a Django-

Posted by sebpiq on Stack Overflow See other posts from Stack Overflow or by sebpiq
Published on 2010-04-09T08:05:12Z Indexed on 2010/04/09 10:13 UTC
Read the original article Hit count: 427

Filed under:
|

Hi ! I'm currently doing a firewall management application for Django, here's the (simplified) model :

class Port(models.Model):
    number = models.PositiveIntegerField(primary_key=True)
    application = models.CharField(max_length=16, blank=True)

class Rule(models.Model):
    port = models.ForeignKey(Port)
    ip_source = models.IPAddressField()
    ip_mask = models.IntegerField(validators=[MaxValueValidator(32)])
    machine = models.ForeignKey("vmm.machine")

What I would like to do, however, is to display to the user a form for entering rules, but with a very different organization than the model :

Port 80

O Not open

O Everywhere

O Specific addresses :

--------- delete field

--------- delete field

+ add address field

Port 443

... etc

Where Not open means that there is no rule for the given port, Everywhere means that there is only ONE rule (0.0.0.0/0) for the given port, and with specific addresses, you can add as many addresses as you want (I did this with JQuery), which will make as many rules.

Now I did a version completely "handmade", meaning that I create the forms entirely in my templates, set input names with a prefix, and parse all the POSTed stuff in my view (which is quite painful, and means that there's no point in using a web framework).

I also have a class which aggregates the rules together to easily pre-fill the forms with the informations "not open, everywhere, ...". I'm passing a list of those to the template, therefore it acts as an interface between my model and my "handmade" form :

class MachinePort(object):
    def __init__(self, machine, port):
        self.machine = machine
        self.port = port

    @property
    def fully_open(self):
        for rule in self.port.rule_set.filter(machine=self.machine):
            if ipaddr.IPv4Network("%s/%s" % (rule.ip_source, rule.ip_mask)) == ipaddr.IPv4Network("0.0.0.0/0"):
                return True
        else :
            return False

    @property
    def partly_open(self):
        return bool(self.port.rule_set.filter(machine=self.machine)) and not self.fully_open

    @property
    def not_open(self):
        return not self.partly_open and not self.fully_open

But all this is rather ugly ! Do anyone of you know if there is a classy way to do this ? In particular with the form... I don't know how to have a form that can have an undefined number of fields, neither how to transform these fields into Rule objects (because all the rule fields would have to be gathered from the form), neither how to save multiple objects... Well I could try to hack into the Form class, but seems like too much work for such a special case. Is there any nice feature I'm missing ?

© Stack Overflow or respective owner

Related posts about django

Related posts about python