2010-03-18 23 views
46

Me gustaría tener en mi modelo un CharField de longitud fija. En otras palabras, quiero que solo una longitud especificada sea válida.Django: CharField con longitud fija, ¿cómo?

Me trataron 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 y min_length al mismo tiempo).

¿Hay alguna otra manera rápida?

Gracias

EDIT:

Siguiendo las sugerencias de algunas personas Voy a ser un poco más específico:

Mi modelo es la siguiente:

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.

I.E. si alguien inserta '4b' django da un error porque espera una cadena de 4 caracteres.

Así que probé 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 único "max_length" O "min_length".

Leo 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 manera de resolver el problema.

Gracias de nuevo

+0

¿por qué alguien me dio un valor de -1? ¿es una pregunta estúpida? –

+0

¿Qué error te da? –

+0

Giovanni, sea más específico y publique el error que se planteó. Además, asegúrese de verificar primero los documentos de Django. Cheers – Nacho

Respuesta

34

Charfield casos campo de modelo de base de datos sólo tienen un parámetro de max_length, como se indica en la docs. Probablemente esto se deba a que solo existe una contracción de longitud de caracteres máxima equivalente en SQL.

Form Field CharField objetos, 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 así:

# 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) 
+7

Como alternativa, podría escribir un validador personalizado que arroje un ValidationError si la longitud no es 4, de esta manera, la base de datos nunca contendrá una longitud incorrecta, incluso si no están utilizando su VolumeForm: https: //docs.djangoproject .com/es/dev/ref/models/instances/# validating-objects – Ben

+0

generará varchar, no char (en mysql sabor). El parche fijo es más rápido que varchar. –

16

puede escribir un validador personalizada según lo sugerido por @Ben. A partir de la fecha de esta respuesta las instrucciones para hacer esto se pueden encontrar en https://docs.djangoproject.com/en/dev/ref/validators/

El código sería algo como esto (copiado 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]) 
63

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')]) 

Desde el Django Docs: class RegexValidator(\[regex=None, message=None, code=None\])

regex: Una expresión regular válida para que coincida. 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: código de error devuelto por ValidationError. No es importante para su caso de uso, puede dejarlo fuera.

Tenga cuidado, la expresión regular sugerida por mí permitirá cualquier carácter, incluso 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;).

+0

+1 parece una buena solución, pero explique cómo usarlo;) – supervacuo

+0

@supervacuo Acabo de editarlo para que sea una respuesta más completa. Gracias por tu sugerencia. Suelo adoptar un enfoque minimalista :). – tBuLi

+6

prefiera esto a la respuesta aceptada porque garantiza la longitud correcta incluso si el usuario no está utilizando VolumeForm –

32

Siguiendo la misma línea que la anterior, pero por lo que vale, también podría seguir adelante con MinLengthValidator que django suministra. Trabajó para mi. El código sería algo como esto:

from django.core.validators import MinLengthValidator 
... 
class Volume(models.Model): 
volumenumber = models.CharField('Volume Number', max_length=4, validators=[MinLengthValidator(4)]) 
... 
+8

Esta es la mejor respuesta. –

+1

¡Respuesta correcta! https://docs.djangoproject.com/en/1.11/ref/validators/#minlengthvalidator – Raptor

Cuestiones relacionadas