web-dev-qa-db-fra.com

Django: CharField à longueur fixe, comment?

J'aimerais avoir dans mon modèle un CharField de longueur fixe. En d'autres termes, je veux que seule une longueur spécifiée soit valide.

J'ai essayé de faire quelque chose comme

volumenumber = models.CharField('Volume Number', max_length=4, min_length=4)

mais cela me donne une erreur (il semble que je puisse utiliser à la fois max_length et min_length en même temps).

Existe-t-il un autre moyen rapide?

Merci

ÉDITER:

En suivant les suggestions de certaines personnes, je serai un peu plus précis:

Mon modèle est le suivant:

class Volume(models.Model):
    vid = models.AutoField(primary_key=True)
    jid = models.ForeignKey(Journals, db_column='jid', null=True, verbose_name = "Journal")
    volumenumber = models.CharField('Volume Number')
    date_publication = models.CharField('Date of Publication', max_length=6, blank=True)
    class Meta:
        db_table = u'volume'
        verbose_name = "Volume"
        ordering = ['jid', 'volumenumber']
        unique_together = ('jid', 'volumenumber')
    def __unicode__(self):
        return (str(self.jid) + ' - ' + str(self.volumenumber))

Ce que je veux, c'est que le volumenumber soit exactement 4 caractères.

C'EST À DIRE. si quelqu'un insère '4b' Django donne une erreur car il attend une chaîne de 4 caractères.

J'ai donc essayé avec

volumenumber = models.CharField('Volume Number', max_length=4, min_length=4)

mais cela me donne cette erreur:

Validating models...
Unhandled exception in thread started by <function inner_run at 0x70feb0>
Traceback (most recent call last):
  File "/Library/Python/2.5/site-packages/Django/core/management/commands/runserver.py", line 48, in inner_run
    self.validate(display_num_errors=True)
  File "/Library/Python/2.5/site-packages/Django/core/management/base.py", line 249, in validate
    num_errors = get_validation_errors(s, app)
  File "/Library/Python/2.5/site-packages/Django/core/management/validation.py", line 28, in get_validation_errors
    for (app_name, error) in get_app_errors().items():
  File "/Library/Python/2.5/site-packages/Django/db/models/loading.py", line 131, in get_app_errors
    self._populate()
  File "/Library/Python/2.5/site-packages/Django/db/models/loading.py", line 58, in _populate
    self.load_app(app_name, True)
  File "/Library/Python/2.5/site-packages/Django/db/models/loading.py", line 74, in load_app
    models = import_module('.models', app_name)
  File "/Library/Python/2.5/site-packages/Django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/Users/Giovanni/src/djangoTestSite/../djangoTestSite/journaldb/models.py", line 120, in <module>
    class Volume(models.Model):
  File "/Users/Giovanni/src/djangoTestSite/../djangoTestSite/journaldb/models.py", line 123, in Volume
    volumenumber = models.CharField('Volume Number', max_length=4, min_length=4)
TypeError: __init__() got an unexpected keyword argument 'min_length'

Cela n'apparaît évidemment pas si j'utilise uniquement "max_length" OR "min_length".

J'ai lu la documentation sur le site Django et il semble que j'ai raison (je ne peux pas utiliser les deux ensemble) donc je demande s'il y a une autre façon de résoudre le problème.

Merci encore

58
Giovanni Di Milia

Les instances de champ du modèle de base de données CharField ont uniquement un max_length, comme indiqué dans le docs . Cela est probablement dû au fait qu'il n'y a qu'un équivalent de contraint de longueur maximale de caractères dans SQL.

Form Field CharField les objets, en revanche, ont un min_length paramètre. Vous devez donc écrire un ModelForm personnalisé pour ce modèle spécifique et remplacer le formulaire de modèle d'administration par défaut par le formulaire personnalisé.

Quelque chose comme ca:

# admin.py

from Django import forms

...

class VolumeForm(forms.ModelForm):
    volumenumber = forms.CharField(max_length=4, min_length=4)

    class Meta:
        model = Volume


class VolumeAdmin(admin.ModelAdmin):
    form = VolumeForm

...

admin.site.register(Volume, VolumeAdmin)
40
Haes

Vous n'avez même pas besoin d'en écrire un personnalisé. Utilisez simplement le RegexValidator qui Django fournit.

from Django.core.validators import RegexValidator

class MyModel(models.Model):
    myfield = models.CharField(validators=[RegexValidator(regex='^.{4}$', message='Length has to be 4', code='nomatch')])

À partir du Django Docs: class RegexValidator(\[regex=None, message=None, code=None\])

regex: expression régulière valide à mettre en correspondance. Pour plus d'informations sur l'expression régulière dans Python consultez cet excellent HowTo: http://docs.python.org/howto/regex.html

message: Le message retourné à l'utilisateur en cas d'échec.

code: code d'erreur renvoyé par ValidationError. Pas important pour votre cas d'utilisation, vous pouvez le laisser de côté.

Attention, l'expression régulière suggérée par moi autorisera tous les personnages, y compris les espaces. Pour autoriser uniquement les caractères alphanumériques, remplacez le '.' avec '\ w' dans l'argument regex. Pour d'autres exigences, ReadTheDocs;).

77
tBuLi

Un peu dans le même sens que ci-dessus, mais pour ce que ça vaut, vous pouvez également aller de l'avant avec MinLengthValidator qui Django fournit. A fonctionné pour moi. Le code ressemblerait à ceci:

from Django.core.validators import MinLengthValidator
...
class Volume(models.Model):
volumenumber = models.CharField('Volume Number', max_length=4, validators=[MinLengthValidator(4)])
...
57
Chetan

Vous pouvez écrire un validateur personnalisé comme suggéré par @Ben. À la date de cette réponse, les instructions pour ce faire peuvent être trouvées sur https://docs.djangoproject.com/en/dev/ref/validators/

Le code serait quelque chose comme ça (copie à partir du lien):

from Django.core.exceptions import ValidationError

def validate_length(value,length=6):
    if len(str(value))!=length:
        raise ValidationError(u'%s is not the correct length' % value)

from Django.db import models

class MyModel(models.Model):
    constraint_length_charField = models.CharField(validators=[validate_length])
16
tjb