Django : presenting a form very different from the model and with multiple field values in a Django-
- by sebpiq
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 ?