Login

FixedCharField and related

Author:
andresj
Posted:
November 15, 2008
Language:
Python
Version:
1.0
Score:
0 (after 0 ratings)

FixedCharField is used similarly to CharField, but takes a length attribute, and will only accept strings with that exact length.

class Student(models.Model):
    student_id = FixedCharField(length=8)

It currently only supports mysql, sqlite3, and oracle. The port to postgresql should be straightforward but I'm not sure about it so I haven't added it yet.

This is a copy-paste (plus a couple of adaptations) from my project Chango, found at http://launchpad.net/chango/, so in order to keep up with latest updates it might be a good idea to use code directly from there.

 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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
############################
## This goes in forms.py  ##
############################

from django import forms
from django.utils.translation import ugettext_lazy as _
from django.forms.util import ValidationError
from django.forms.widgets import TextInput, PasswordInput

class FixedCharField(forms.CharField):
    default_error_messages = {
        'wrong_length': _(u'Ensure this value has exactly %(set_length)d characters (it has %(value_length)d).'),
    }

    def __init__(self, length, *args, **kwargs):
        self.length = length
        super(FixedCharField, self).__init__(*args, **kwargs)

    def clean(self, value):
        "Validates length. Returns a Unicode object."
        value = super(FixedCharField, self).clean(value)
        value_length = len(value)
        if value_length != self.length:
            raise ValidationError(self.error_messages['wrong_length'] % {'set_length': self.length, 'value_length': value_length})
        return value

    def widget_attrs(self, widget):
        if isinstance(widget, (TextInput, PasswordInput)):
            # The HTML attribute is maxlength, not max_length.
            return {'maxlength': str(self.length)}

############################
## This goes in models.py ##
############################

from myapp.forms import FixedCharField as FixedCharFormField

from django.db import models
from django.db import connection
from django.conf import settings
from django.utils.datastructures import DictWrapper

class FixedCharField(models.Field):
    def __init__(self, verbose_name=None, name=None, primary_key=False,
                 length=None, *args, **kwargs):
        if length == None:
            raise Exception("FixedCharField needs length attribute.")
        self.length = length
        
        # The kwargs will never include verbose_name nor name. (TODO: Really?)
        kwargs['verbose_name'] = verbose_name
        kwargs['name'] = name
        
        super(FixedCharField, self).__init__(*args, **kwargs)

    def db_type(self):
        data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
        
        if settings.DATABASE_ENGINE == 'mysql':
            return 'char(%(length)s)' % data
        elif settings.DATABASE_ENGINE == 'sqlite3':
            return 'char(%(length)s)' % data
        elif settings.DATABASE_ENGINE == 'oracle':
            return 'VARCHAR2(%(length)s)' % data
        else:
            return models.CharField.db_type(self)

#    def get_internal_type(self):
#        return "FixedCharField"

    def to_python(self, value):
        return models.CharField(self, value)

    def formfield(self, **kwargs):
        defaults = {'form_class': FixedCharFormField, 
                    'length': self.length}
        defaults.update(kwargs)
        return super(FixedCharField, self).formfield(**defaults)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 2 weeks ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 10 months, 1 week ago
  5. Help text hyperlinks by sa2812 11 months ago

Comments

stringify (on November 15, 2008):

How does this differ from using a CharField with a max_length and min_length of equal value?

#

stringify (on November 16, 2008):

Oh it appears only forms.CharField has a min_length argument. db.models.CharField does not.

#

Please login first before commenting.