Python 如何查找Django admin中存储为整数的自定义ip地址字段?
在我的Django模型中,我创建了自定义MyIPAddressField,它作为整数存储在mysql后端。为此,我实现了To_python、get_db_prep_value、get_iternal_type(返回PositiveIntegerField)和formfield方法(使用stock IPAddressField作为form_类) 唯一的问题是在ModelAdmin中的内置搜索等情况下的字段查找。因此,问题是如何实现get_db_prep_查找以执行基于字符串的查找类型,如“contains”、“regex”、“startswith”、“endswith” Mysql有一个特殊的函数inet_ntoa(),但我不知道如何指导ORM在管理搜索查询中使用它。例如:从ip类似“%search\u term%”的表中选择inet\u ntoa(ip\u地址)作为ip。为什么自定义字段在python端执行类型转换,而不是在数据库端 EDIT1:可能还有另一种解决搜索问题的方法-不要将整型列转换为字符串,而是将搜索参数拆分为子网/掩码,并执行一些二进制数学,将它们与整型IP值进行比较 EDIT2:这是我目前的代码: models.py:Python 如何查找Django admin中存储为整数的自定义ip地址字段?,python,mysql,django,Python,Mysql,Django,在我的Django模型中,我创建了自定义MyIPAddressField,它作为整数存储在mysql后端。为此,我实现了To_python、get_db_prep_value、get_iternal_type(返回PositiveIntegerField)和formfield方法(使用stock IPAddressField作为form_类) 唯一的问题是在ModelAdmin中的内置搜索等情况下的字段查找。因此,问题是如何实现get_db_prep_查找以执行基于字符串的查找类型,如“cont
class MyIPField(models.Field):
empty_strings_allowed = False
__metaclass__ = models.SubfieldBase
def get_db_prep_value(self, value):
if value is None: return None
return unpack('!L', inet_aton(value))[0]
def get_internal_type(self):
return "PositiveIntegerField"
def to_python(self, value):
if type(value).__name__ in ('NoneType', 'unicode'): return value
return inet_ntoa(pack('!L', value))
def formfield(self, **kwargs):
defaults = {'form_class': IPAddressField}
defaults.update(kwargs)
return super(MyIPField, self).formfield(**defaults)
class MyManager(models.Manager):
def get_query_set(self):
return super(MyManager, self).get_query_set().extra(select={'fakeip': "inet_ntoa(ip)"})
class Address(models.Model):
# ... other fields are skipped (Note: there was several foreign keys)
ip = MyIPField(u"IP address", unique=True)
objects = AddressManager()
def __unicode__(self):
return self.ip
admin.py:
class AddressAdmin(admin.ModelAdmin):
list_display = ('address',) # ... some fields are skipped from this example
list_display_links = ('address',)
search_fields = ('fakeip', )
admin.site.register(Address, AddressAdmin)
但当我使用管理员变更列表搜索框时,我得到错误“无法将关键字'fakeip'解析到字段中。选项有:ip,id”。有没有可能愚弄Django,让它认为fakeip是一个真正的领域
使用标准的IPAddressField(基于字符串)不适合我的需要,也不适合切换到以正确格式存储的Postgres
此外,我还查看了Django管理内部(options.py和views/main.py),我发现如果不进行大量复制/粘贴,就很难定制变更列表类或搜索机制。我认为Django admin比它强大。您可以指示ORM在SQL查询中添加一个额外字段,如下所示:
IPAddressModel.objects.extra(select={'ip': "inet_ntoa(ip_address)"})
这会将SELECT inet\u ntoa(ip\u地址)作为ip
添加到查询中,并将一个字段ip
添加到对象中。您可以在WHERE子句中使用新的合成字段
你确定你真的不想要类似于WHERE(ip\u地址&0xffff0000)=inet\u aton('192.168.0.0')
?或者您真的想在日志中的某个地方找到包含编号119
的所有ip地址吗
如果后缀
是CIDR符号中的/24:
mask = 0xffffffff ^ 0xffffffff >> suffix
在WHERE条款中添加:
(ip_address & mask) = (inet_aton(prefix) & mask)
基本上我想在change_list管理员视图中使用搜索框。在简单的情况下,子字符串搜索就足够了,但CIDR表示法非常受欢迎。当我将其用于模型实例时,您的解决方案是有效的,但我不知道如何将这个伪sql计算字段添加到模型本身,并能够通过添加搜索字段=('ip',)@Max,只要使用Django内置的IPAddressField,麻烦就会过去。为什么要浪费数周的时间在数据库中保存几个字节?当您第一次需要存储IPv6地址时,这个出色的方案会发生什么?我个人已经浪费了很多时间试图在比SQL更难的领域中与ORM进行争论。不值得。