gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 08:38:29 28 4
gpt4 key购买 nike

在我的 Django 模型中,我创建了自定义的 MyIPAddressField,它作为整数存储在 mysql 后端。为此,我实现了 to_python、get_db_prep_value、get_iternal_type(返回 PositiveIntegerField)和 formfield 方法(使用常用 IPAddressField 作为 form_class)。

唯一的问题是在 ModelAdmin 中的内置搜索等情况下的字段查找。那么,问题是如何实现 get_db_prep_lookup 来执行基于字符串的查找类型,如“contains”、“regex”、“startswith”、“endswith”?

Mysql 有特殊函数 inet_ntoa() 但我不知道如何指示 ORM 在管理搜索查询中使用它。例如:SELECT inet_ntoa(ip_address) as ip FROM table WHERE ip LIKE '%search_term%'。为什么自定义字段在 python 端执行类型转换而不在数据库端执行类型转换?

EDIT1:可能还有另一种解决搜索问题的方法 - 不要将整数列转换为字符串,而是将搜索参数拆分为子网/掩码并执行一些二进制数学运算以将它们与整数 IP 值进行比较。

EDIT2:到目前为止,这是我的代码:

模型.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

管理员.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),我发现没有简单的方法可以自定义 ChangeList 类或搜索机制,而无需大量复制/粘贴。我认为 Django 管理器比它更强大。

最佳答案

您可以指示 ORM 向您的 SQL 查询添加一个额外的字段,如下所示:

IPAddressModel.objects.extra(select={'ip': "inet_ntoa(ip_address)"})

这会将 SELECT inet_ntoa(ip_address) as ip 添加到查询中,并将字段 ip 添加到您的对象中。您可以在 WHERE 子句中使用新的合成字段。

你确定你真的不想要像 WHERE (ip_address & 0xffff0000) = inet_aton('192.168.0.0') 这样的东西吗?或者您是否真的想在您的日志中的某处找到所有包含数字 119 的 IP 地址?

如果 suffix 是来自 CIDR 表示法的/24:

mask = 0xffffffff ^ 0xffffffff >> suffix

添加到 WHERE 子句:

(ip_address & mask) = (inet_aton(prefix) & mask)

关于python - 如何查找在 Django-admin 中存储为整数的自定义 ip 地址字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/541115/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com