我正在尝试使用" limit_choices_to" Django OneToOneField中的功能,我想限制选择的上游是另一个ForeignKey。我在管理员中设置的错误是:
invalid literal for int() with base 10: 'Storage Array'
我认为这是因为它正在查看asset_type列中的实际值,它是一个整数外键。我需要能够根据外键的字段值而不是键值本身来限制选择。
基本上我要完成的是让管理区域(和其他表单)只允许您在添加新资产时选择有效的资产类型。例如,如果我要添加"存储阵列"与之关联的上游资产应该只允许为存储阵列的asset_type。
这是我的模特:
from django.db import models
from localflavor.us.us_states import STATE_CHOICES
# Table of brand names of assets
class Brand(models.Model):
brand = models.CharField(max_length=128, unique=True)
def __unicode__(self):
return self.brand
# Table of device types for assets, e.g. "Storage Array"
class Device(models.Model):
device_type = models.CharField(max_length=128, unique=True)
device_url_slug = models.SlugField(max_length=70, unique=True)
class Meta:
verbose_name = "device type"
verbose_name_plural = "device types"
def __unicode__(self):
return self.device_type
# Table of asset locations
class Location(models.Model):
site_name = models.CharField(max_length=128, unique=True)
site_nick = models.CharField(max_length=5, unique=True)
address_line_one = models.CharField(max_length=256)
address_line_two = models.CharField(max_length=256, null=True, blank=True)
address_city = models.CharField(max_length=32)
address_state = models.CharField(max_length=2, choices=STATE_CHOICES, null=True, blank=True)
address_zip = models.CharField(max_length=5)
def __unicode__(self):
return self.site_name
# Table of Environments, e.g. "Production"
class Environment(models.Model):
environment = models.CharField(max_length=128, unique=True)
def __unicode__(self):
return self.environment
class Credentials(models.Model):
AUTH_CHOICES = (
('SSH', 'Standard SSH'),
('SSH-Key', 'SSH with Key-based login'),
('HTTP', 'Standard HTTP'),
('HTTPS', 'Secure HTTP'),
('API', 'API Based'),
('SNMP', 'SNMP Based'),
)
SNMP_VERSIONS = (
('v1', 'SNMP v1'),
('v3', 'SNMP v3'),
)
auth_method = models.CharField(max_length=32, choices=AUTH_CHOICES)
auth_username = models.CharField(max_length=32)
auth_password = models.CharField(max_length=32, null=True, blank=True)
auth_snmp_version = models.CharField(max_length=2, choices=SNMP_VERSIONS, null=True, blank=True)
auth_snmp_community = models.CharField(max_length=128, null=True, blank=True)
class Meta:
verbose_name = "credentials"
verbose_name_plural = "credentials"
def __unicode__(self):
return self.auth_method
class Asset(models.Model):
asset_name = models.CharField(max_length=128, unique=True)
asset_type = models.ForeignKey(Device)
brand = models.ForeignKey(Brand)
model = models.CharField(max_length=128)
serial = models.CharField(max_length=256)
location = models.ForeignKey(Location)
environment = models.ForeignKey(Environment)
datacenter_room = models.CharField(max_length=32, null=True, blank=True)
grid_location = models.CharField(max_length=32, null=True, blank=True)
mgmt_address = models.CharField(max_length=128)
notes = models.TextField(null=True, blank=True)
def __unicode__(self):
return self.asset_name
class StorageArray(models.Model):
OS_NAME_CHOICES = (
('Data OnTap', 'NetApp Data OnTap'),
)
OS_TYPE_CHOICES = (
('7-Mode', 'NetApp 7-Mode'),
('cDOT', 'NetApp Clustered'),
)
HA_TYPE_CHOICES = (
('Standalone', 'Standalone System'),
('HA Pair', 'HA Pair'),
('Clustered', 'Clustered'),
)
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type': 'Storage Array'})
os_name = models.CharField(max_length=32, choices=OS_NAME_CHOICES, null=True, blank=True)
os_version = models.CharField(max_length=16, null=True, blank=True)
os_type = models.CharField(max_length=16, choices=OS_TYPE_CHOICES, null=True, blank=True)
array_ha_type = models.CharField(max_length=32, choices=HA_TYPE_CHOICES, null=True, blank=True)
array_partner = models.CharField(max_length=128, null=True, blank=True)
credentials = models.ForeignKey(Credentials, null=True, blank=True)
class Meta:
verbose_name = "storage array"
verbose_name_plural = "storage arrays"
def __unicode__(self):
return self.asset.asset_name
class SANSwitch(models.Model):
OS_NAME_CHOICES = (
('FabricOS', 'Brocade FabricOS'),
)
SWITCH_TYPE_CHOICES = (
('Standalone', 'Standalone Switch'),
('Director', 'Director'),
('Router', 'Multiprotocol Router'),
('Blade', 'Blade Chassis IO Module'),
)
SWITCH_ROLE_CHOICES = (
('Core', 'Core'),
('Edge', 'Edge'),
('AG', 'Access Gateway'),
)
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type': 'SAN Switch'})
os_name = models.CharField(max_length=32, choices=OS_NAME_CHOICES, null=True, blank=True)
os_version = models.CharField(max_length=16, null=True, blank=True)
switch_type = models.CharField(max_length=32, choices=SWITCH_TYPE_CHOICES, null=True, blank=True)
switch_role = models.CharField(max_length=32, choices=SWITCH_ROLE_CHOICES, null=True, blank=True)
credentials = models.ForeignKey(Credentials, null=True, blank=True)
class Meta:
verbose_name = "san switch"
verbose_name_plural = "san switches"
def __unicode__(self):
return self.asset.asset_name
答案 0 :(得分:3)
我自己解决了这个问题!
似乎可以进一步转化为可以使用python / django内置的double underscore notation的关系。
解决我的问题:
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type': 'Storage Array'})
成为:
asset = models.OneToOneField(Asset, primary_key=True, limit_choices_to={'asset_type__device_type': 'Storage Array'})