Reputation: 151
Is it possible to add a variable to Django Model Field.choices?
I lose functionality when I have to add it statically.
IP_CHOICES = (
('192.168.1.0', '192.168.1.0'),
)
ip_address = models.IPAddressField(choices=IP_CHOICES, unique=True, blank=True)
I use a Python IP Interpreter called IPy, to calculate the correct IP block.
ip = IP(self.network + slash)
for rangeip in enumerate(ip[2:-1]):
IP_CHOICES = (
("%s" %rangeip, "%s" %rangeip)
)
Is this possible? If so, please help. Been trying to hack it for the past week and got no where. Any help is appreciated.
Please view Model Class.
#IP Block Class
class IP_block(models.Model):
network = models.IPAddressField(unique=True)
slash = models.ForeignKey(Subnet, verbose_name='CIDR')
subnet = models.CharField(max_length=64, blank=True)
gateway_ip = models.CharField(max_length=64, blank=True)
broadcast_ip = models.CharField(max_length=64, blank=True)
ip_range = models.TextField(blank=True, verbose_name='Available IP Range')
dslam = models.ManyToManyField(Dslam, verbose_name='Dslam', blank=True)
#ip block and range save function
def save(self, *args, **kwargs):
slash = unicode(self.slash)
broadcast = IP(self.network + slash).broadcast()
subnet = IP(self.network+slash).strNetmask()
self.broadcast_ip = broadcast
self.subnet = subnet
ip = IP(self.network + slash)
for gateway in ip[1]:
self.gateway_ip = gateway
#rangeip for loop
ip = IP(self.network + slash)
if self.ip_range:
print 'no override'
else:
for rangeip in ip[2:-1]:
self.ip_range += "%s\n" %rangeip
IP_CHOICE = "(%s" %rangeip + ", %s)," %rangeip
#ip_list select
ip_list = models.CharField(choices=IP_CHOICE, max_length=128, blank=True)
super(IP_block, self).save(*args, **kwargs)
class Meta:
verbose_name_plural = 'IP Blocks'
def __unicode__(self):
return self.network
Upvotes: 0
Views: 2121
Reputation: 599796
You have many fairly basic errors here. For example, in your suggested syntax:
for rangeip in enumerate(whatever):
IP_CHOICES = (do_something)
It should be obvious to you that you are simply overwriting IP_CHOICES each time through the loop. At the end of the loop, it will simply have the value of the last iteration, which isn't by itself in a suitable format for choices
.
You have this same pattern a number of times. Please think about what it is actually doing.
But there's an even worse error in your save function, where you have this line:
ip_list = models.CharField(choices=IP_CHOICE, max_length=128, blank=True)
I have absolutely no idea what you think that is doing. You can't define a field in the middle of a save method. You can set a field's value, but you can't suddenly define a new field (again, please think about it: how would that work with the database? And remember fields are class-level attributes: all instances of that model need to have the same field selection).
It's almost impossible to understand what you are actually trying to do. I think you are trying to provide a choice of IP addresses for one field in the model (ip_list
), once the user has set the range in another field (ip_range
). (It would have been useful if you'd stated that explicitly up front.)
The place to do this is in the form, not in the model. Setting choices
on a model field is really just a shortcut to setting them on forms automatically created from that model, but if you need to do something dynamic you need to define the form yourself and put the logic there. I guess it would be something like this:
class IPBlockForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(IPForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.ip_range:
ip_list_choices = get_ip_list_from_wherever(self.instance_ip_range)
self.fields['ip_list'] = forms.ChoiceField(choices=ip_list_choices)
class Meta:
model = IP_block
But naturally you need to fix the other logic errors in your save
method, which I mention above, first.
Upvotes: 3