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
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)
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;).
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)])
...
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])