Hello guys,

I'm running django on a legacy database and in some cases the values
stored in the tables have to be converted before the can be displayed
and also have to be converted bevore bein saved to the database.

Example:

A table for storing IP addresses:

The address field contains values that are  packed binary format
representations of the human readable value e.g:
000000000000000000000000d55f026c resolves to 213.95.2.108.

I already figured out how to convert between those tow back and forth
with the socket module.
I also figured out how I can make it work in django.

But I'm not happy with the solution I found and I suspect that there
might be a better way to do it.

Currently I'm doing it in the following way:

I have a custom ModelField:

class IpAddrField(models.CharField):
    __metaclass__ = models.SubfieldBase
    default_error_messages = {
        'invalid' : _('%s ist keine valide IP-Adresse.')
    }
    def get_internal_type(self):
        return "CharField"

    def to_python(self, value):
        print "               ---------- ModelField to_python got: %s" % value
        value = db_to_ipaddr(value)
        print "               ---------- ModellField to_python
returning: %s" % value

        return value

    def clean(self,value,model_instance):
        print "               ---------- ModelField clean got: %s" % value
        try:
            value =  ipaddr_to_db(value)
        except (socket.error, ValueError):
            raise
exceptions.ValidationError(self.error_messages['invalid'] % value)
        self.validate(value, model_instance)
        self.run_validators(value)
        print "               ---------- ModelField clean returning: %s" % value
        return value

    def get_prep_value(self,value):
        print "               ---------- MoldelField get_prep got: %s" % value
        value =  ipaddr_to_db(value)
        print "               ---------- MoldelField get_prep
returning: %s" % value
        return value

    def formfield(self, **kwargs):
        defaults = {'form_class': IpAddrFormField}
        defaults.update(kwargs)
        return super(IpAddrField, self).formfield(**defaults)


The code for the custom formField looks like this:

class IpAddrFormField(forms.CharField):
    default_error_messages = {
        'invalid' : _('%s ist keine valide IP-Adresse.')
    }

    def to_python(self,value):

        print "               ---------- FormField to_python got: %s" % value

        try:
            value = ipaddr_to_db(value)
        except socket.error:
            raise
exceptions.ValidationError(self.error_messages['invalid'] % value)

        print "               ---------- FormField to_python
returning: %s" % value

        return value

    def clean(self,value):
        "convert the literal value to the db representation"
        print "               ---------- FormField clean got: %s" % value

        try:
            value = self.to_python(value)
        except socket.error:
            raise
exceptions.ValidationError(self.error_messages['invalid'] % value)
        self.validate(value)
        self.run_validators(value)
        print "               ---------- FormField clean return: %s" % value

        return value


So when I run this code and send a form with a valid IP address it works.

Here is the log output of a successful update:

               ---------- ModelField to_python got:
000000000000000000000000d55f026d
               ---------- ModellField to_python returning: 213.95.2.109
               ---------- FormField clean got: 213.95.2.108
               ---------- FormField to_python got: 213.95.2.108
               ---------- FormField to_python returning:
000000000000000000000000d55f026c
               ---------- FormField clean return:
000000000000000000000000d55f026c
               ---------- ModelField to_python got:
000000000000000000000000d55f026c
               ---------- ModellField to_python returning: 213.95.2.108
               ---------- ModelField clean got: 213.95.2.108
               ---------- ModelField clean returning:
000000000000000000000000d55f026c
               ---------- ModelField to_python got:
000000000000000000000000d55f026c
               ---------- ModellField to_python returning: 213.95.2.108
               ---------- ModelField to_python got:
000000000000000000000000d55f026d
               ---------- ModellField to_python returning: 213.95.2.109
               ---------- MoldelField get_prep got: 213.95.2.108
               ---------- MoldelField get_prep returning:
000000000000000000000000d55f026c
---------------- in post save (this is a post_save hook, not sure if
this is relevant here)
               ---------- MoldelField get_prep got: 213.95.2.108
               ---------- MoldelField get_prep returning:
000000000000000000000000d55f026c
---------------- in post save  (this is a post_save hook, not sure if
this is relevant here)
---------------- in post save  (this is a post_save hook, not sure if
this is relevant here)
[18/Feb/2011 10:13:56] "POST /services/ipkunde/15679/update/ HTTP/1.1" 302 0
               ---------- ModelField to_python got:
000000000000000000000000d55f026c
               ---------- ModellField to_python returning: 213.95.2.108

This is a lot of back and forth conversion and I'm not so happy with
this. The code might break if the django validation thing changes
slightly or something unexpected happens.

On top of that, I feel like working against the ideas of whole validation thing.

Can someone suggest a better solution? Maybe an easier one. Or a more
stable one? There are quite some fields where I have to do such
conversions. I'm really trying to find a clean solution which is not
just tricking the framework.

Looking forward to you comments...

Regards
 Roman

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to