Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何查找Django admin中存储为整数的自定义ip地址字段?_Python_Mysql_Django - Fatal编程技术网

Python 如何查找Django admin中存储为整数的自定义ip地址字段?

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

在我的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:

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进行争论。不值得。