How to find a custom ip address field saved as an integer in Django-admin?

In my Django model, I created my own MyIPAddressField, which is stored as a whole in a mysql server. For this, I implemented to_python, get_db_prep_value, get_iternal_type (returns PositiveIntegerField) and formfield methods (uses the IPAddressField margin as form_class).

The only problem is a field search in cases such as the built-in search in ModelAdmin. So the question is how to implement get_db_prep_lookup to do string search types like 'contains', 'regex', 'startswith', 'endswith'?

Mysql has a special function inet_ntoa (), but I don’t know how to tell ORM to use it in administrator search requests. For example: SELECT inet_ntoa (ip_address) as ip FROM table WHERE ip LIKE '% search_term%'. Why do custom fields perform type casting on the python side, but not the database side?

EDIT1: There may be another way to solve the search problem - do not convert the integer column to a string, but instead separate the search argument into a subnet / mask and do some binary math to compare them with an integer IP value.

EDIT2: this is my code:

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), ChangeList /. , Django , .

+3
1

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')? IP- , 119 -?

suffix /24 CIDR:

mask = 0xffffffff ^ 0xffffffff >> suffix

WHERE:

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

Source: https://habr.com/ru/post/1703091/


All Articles