template - ifequal django
Django: CharField con longitud fija, ¿cómo? (4)
Me gustaría tener en mi modelo un CharField de longitud fija. En otras palabras, quiero que solo una longitud especificada sea válida.
Traté de hacer algo como
volumenumber = models.CharField(''Volume Number'', max_length=4, min_length=4)
pero me da un error (parece que puedo usar tanto max_length como min_length al mismo tiempo).
¿Hay otra manera rápida?
Gracias
EDITAR:
Siguiendo las sugerencias de algunas personas, seré un poco más específico:
Mi modelo es este:
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))
Lo que quiero es que el volumenumber
debe tener exactamente 4 caracteres.
IE si alguien inserta ''4b'' django da un error porque espera una cadena de 4 caracteres.
Así que lo intenté con
volumenumber = models.CharField(''Volume Number'', max_length=4, min_length=4)
pero me da este error:
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''
Eso, obviamente, no aparece si uso solo "max_length" O "min_length".
Leí la documentación en el sitio web de django y parece que tengo razón (no puedo usar ambas cosas juntas), así que estoy preguntando si hay otra forma de resolver el problema.
Gracias de nuevo
Las instancias de campo del modelo de base de datos de CharField solo tienen un parámetro max_length
, como se indica en los docs . Probablemente esto se deba a que solo existe una contracción de longitud de caracteres máxima equivalente en SQL.
Los objetos Form Field CharField , por otro lado, tienen un parámetro min_length
. Por lo tanto, tendría que escribir un Modelo de formulario personalizado para este modelo específico y anular el formulario de modelo de administrador predeterminado con el personalizado.
Algo como eso:
# 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)
Ni siquiera tiene que escribir uno personalizado. Simplemente use el RegexValidator
que Django suministra.
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'')])
De los documentos de Django: class RegexValidator(/[regex=None, message=None, code=None/])
regex
: una expresión regular válida para unir. Para obtener más información sobre expresiones regulares en Python, consulte este excelente HowTo: http://docs.python.org/howto/regex.html
message
: el mensaje devuelto al usuario en caso de error.
code
: code
error devuelto por ValidationError. No es importante para su caso de uso, puede dejarlo fuera.
Cuidado, la expresión regular sugerida por mí permitirá cualquier caracter incluyendo el espacio en blanco. Para permitir solo caracteres alfanuméricos, sustituya el ''.'' con ''/ w'' en el argumento de expresión regular. Para otros requisitos, ReadTheDocs;).
Puede escribir un Validador personalizado como lo sugiere @Ben. A partir de la fecha de esta respuesta, las instrucciones para hacerlo se encuentran en https://docs.djangoproject.com/en/dev/ref/validators/
El código sería algo como esto (copiar desde el enlace):
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_validate_length])
Siguiendo la misma línea que arriba, pero por lo que vale, también podría seguir adelante con MinLengthValidator que django suministra. Trabajó para mi. El código se vería así:
from django.core.validators import MinLengthValidator
...
class Volume(models.Model):
volumenumber = models.CharField(''Volume Number'', max_length=4, validators=[MinLengthValidator(4)])
...