[django] model field für python dicts...

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Samstag 18. April 2009, 23:53

Hier hab ich mir ein DictField gebaut. Damit kann man ein python dict in ein django model field packen, soweit klappt alles. Ich finde es nur ein wenig umständlich:

Code: Alles auswählen

def serialize(data):
    return simplejson.dumps(data, sort_keys=True, indent=4)

def deserialize(stream):
    return simplejson.loads(stream)


class DictFormWidget(forms.Textarea):
    """ form widget for preferences dict """
    def render(self, name, value, attrs=None):
        """
        FIXME: Can we get the original non-serialized db value here?
        """
        value = serialize(value)
        return super(DictFormWidget, self).render(name, value, attrs)


class DictFormField(forms.CharField):
    """ form field for preferences dict """
    widget = DictFormWidget
    
    def clean(self, value):
        """
        validate the form data
        FIXME: How can we get the pref form class for validating???
        """
        value = super(DictFormField, self).clean(value)
        try:
            return deserialize(value)
        except Exception, err:
            raise forms.ValidationError("Can't deserialize: %s" % err)


class DictField(models.TextField):
    """
    A dict field.
    Stores a python dict into a text field. 
    """
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        """ decode the data dict using simplejson.loads() """
        if isinstance(value, dict):
            return value
        return deserialize(value)

    def get_db_prep_save(self, value):
        "Returns field's value prepared for saving into a database."
        assert isinstance(value, dict)
        return serialize(value)

    def formfield(self, **kwargs):
        # Always use own form field and widget:
        kwargs['form_class'] = DictFormField
        kwargs['widget'] = DictFormWidget
        return super(DictField, self).formfield(**kwargs)
Damit man auch im django admin panel einen DB Eintrag "normal" editieren kann, habe ich ein eigenes form field und widget gemacht. Und da liegt auch meine Frage: Ich finde es dumm, das man an zwei Stellen die Wandlung python<->json machen muß. Im model field, im form field und im form widget...
Ich Frage mich wie ich im form field und im widget Zugriff auf die model instance haben kann?

EDIT: btw. Natürlich könnte man auch andere datentypen die json kann nehmen. Ich brauche aber nur dict...
EDIT2: Hier noch ein ähnliches Beispiel: http://trac.pylucid.net/browser/branche ... y?rev=1906

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Sonntag 19. April 2009, 08:23

Ich fand das JSONField ( http://www.djangosnippets.org/snippets/377/ ) recht praktisch. Das funktioniert ähnlich. Leider haben die Django-Entwickler (IMHO falsch) entschieden ( http://code.djangoproject.com/ticket/5965 ) dieses nicht mit in Django aufzunehmen.

Ich sehe, du benutzt ebenfalls simplejson zum Serialisieren. Warum also nicht einfach dieses Feld? Alternativ gibt es ja pickle und http://www.djangosnippets.org/snippets/513/.


Stefan
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Sonntag 19. April 2009, 10:07

Sanke für die beiden Links. Muß ich mir mal näher ansehen. Insbesondere interessiert mich, wie die Felder sich im Admin Bereich verhalten.

Ob ich bei JSON bleiben werde, oder wieder zurück zu meinem eigenen Ding, weiß ich noch nicht. Pickle gefällt mir nicht ganz so, weil man die Daten dann nicht in Roh-Formate ändern kann. Aber das ist im Grunde auch Nebensache.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten