StringListField (database field)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# -*- coding: iso-8859-1 -*-
# $Id: StringListField.py 344 2009-05-06 06:57:27Z tguettler $
# $HeadURL: svn+ssh://svnserver/svn/djangotools/trunk/dbfields/StringListField.py $

# http://www.djangosnippets.org/snippets/1491/

# Django
from django.db import models
from django import forms

class StringListField(models.Field):
    u'''
    Save a list of strings in a CharField (or TextField) column.

    In the django model object the column is a list of strings.
    '''
    __metaclass__=models.SubfieldBase
    SPLIT_CHAR=u'\v'
    def __init__(self, *args, **kwargs):
        self.internal_type=kwargs.pop('internal_type', 'CharField') # or TextField
        super(StringListField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if isinstance(value, list):
            return value
        if value is None:
            return []
        return value.split(self.SPLIT_CHAR)

    def get_internal_type(self):
        return self.internal_type

    def get_db_prep_lookup(self, lookup_type, value):
        # SQL WHERE
        raise NotImplementedError()

    def get_db_prep_save(self, value):
        return self.SPLIT_CHAR.join(value)

    def formfield(self, **kwargs):
        assert not kwargs, kwargs
        return forms.MultipleChoiceField(choices=self.choices)

More like this

  1. Model-driven multiple database router by tga 2 years, 2 months ago
  2. check database interity by d2 3 years, 10 months ago
  3. Pickled Object Field by obeattie 6 years, 4 months ago
  4. path.py FilePathField by tino 3 years, 3 months ago
  5. decorator to add GUID Field to Django Models by trubliphone 1 year, 2 months ago

Comments

dharris (on October 28, 2009):

I've modified this locally to handle saving and loading empty values better.

In get_db_prep_save (line 37-38), I added:

if not value:
    return None

without this, an empty string was saved -- I prefer a NULL in the db.

Line 26-27, I changed this to

if value is None or value == '':
    return []

#

fylb (on August 30, 2012):

When using choices, in order to be able to use the widget, I had to add a validate method:

def validate(self, value, model_instance):
    """
    Validates value and throws ValidationError. Subclasses should override
    this to provide validation logic.
    """
    if not self.editable:
        # Skip validation for non-editable fields.
        return
    if self._choices and value:
        l = value
        if type(value) != list:
            l = [ value ]
        for v in value:
            for option_key, option_value in self.choices:
                if isinstance(option_value, (list, tuple)):
                    # This is an optgroup, so look inside the group for options.
                    for optgroup_key, optgroup_value in option_value:
                        if v == optgroup_key:
                            return
                elif v == option_key:
                    return
            raise exceptions.ValidationError(self.error_messages['invalid_choice'] % v)

    if value is None and not self.null:
        raise exceptions.ValidationError(self.error_messages['null'])

    if not self.blank and value in validators.EMPTY_VALUES:
        raise exceptions.ValidationError(self.error_messages['blank'])

#

(Forgotten your password?)