2010-03-18 33 views
46

Tôi wold muốn có trong mô hình của tôi một CharField với chiều dài cố định. Nói cách khác tôi muốn rằng chỉ có một chiều dài được chỉ định là hợp lệ.Django: CharField với độ dài cố định, như thế nào?

tôi đã cố gắng để làm một cái gì đó giống như

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

nhưng nó mang lại cho tôi một lỗi (có vẻ như là tôi có thể sử dụng cả hai max_length và MIN_LENGTH cùng một lúc).

Có cách nào khác nhanh không?

Cảm ơn

EDIT:

Tiếp theo những gợi ý của một số người mà tôi sẽ được một chút cụ thể hơn:

Mô hình của tôi là thế này:

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

Những gì tôi muốn là volumenumber phải chính xác 4 ký tự.

I.E. nếu ai đó chèn '4b' django đưa ra một lỗi vì nó dự kiến ​​một chuỗi gồm 4 ký tự.

Vì vậy, tôi cố gắng với

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

nhưng nó mang lại cho tôi lỗi này:

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' 

Đó rõ ràng là không xuất hiện nếu tôi chỉ sử dụng "max_length" OR "MIN_LENGTH".

Tôi đọc tài liệu trên trang web django và có vẻ như tôi đúng (tôi không thể sử dụng cả hai), vì vậy tôi hỏi liệu có cách nào khác để giải quyết vấn đề không.

Cảm ơn một lần nữa

+0

tại sao người nào đó cho tôi giá trị -1? nó là một câu hỏi ngu ngốc? –

+0

Lỗi nào cung cấp cho bạn? –

+0

Giovanni, cụ thể hơn và đăng lỗi nào được nêu ra. Ngoài ra, hãy chắc chắn bạn kiểm tra các tài liệu Django đầu tiên. Chúc mừng – Nacho

Trả lời

34

CharField trường hợp lĩnh vực mô hình cơ sở dữ liệu chỉ có một tham số max_length, như đã nêu trong docs. Điều này có lẽ là do chỉ có một độ dài tương đương độ dài ký tự tối đa tương đương trong SQL. Mặt khác,

Form Field CharField đối tượng, có tham số min_length. Vì vậy, bạn sẽ phải viết một ModelForm tùy chỉnh cho mô hình cụ thể này và ghi đè biểu mẫu mô hình quản trị mặc định bằng biểu mẫu tùy chỉnh.

Something như thế:

# 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

Ngoài ra, bạn có thể viết trình xác nhận tùy chỉnh để ném ValidationError nếu độ dài không phải là 4 - theo cách này, cơ sở dữ liệu sẽ không bao giờ chứa độ dài không chính xác, ngay cả khi chúng không sử dụng VolumeForm: https: //docs.djangoproject của bạn .com/vi/dev/ref/models/instances/# validating-objects – Ben

+0

nó sẽ tạo ra varchar, không phải char (trong hương vị mysql). Cố định char nhanh hơn varchar. –

16

Bạn có thể viết một Validator tùy chỉnh theo đề nghị của @Ben. Tính đến ngày câu trả lời này hướng dẫn để thực hiện điều này có thể được tìm thấy tại https://docs.djangoproject.com/en/dev/ref/validators/

Mã này sẽ là một cái gì đó như thế này (sao chép từ liên kết):

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

Bạn thậm chí không phải viết một tùy chỉnh. Chỉ cần sử dụng RegexValidator mà Django cung cấp.

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

Từ Django Documents: class RegexValidator(\[regex=None, message=None, code=None\])

regex: Một biểu thức chính quy hợp lệ để phù hợp. Để biết thêm về regex trong Python, hãy kiểm tra cách thức xuất sắc này HowTo: http://docs.python.org/howto/regex.html

message: Thư trả lại cho người dùng trong trường hợp không thành công.

code: mã lỗi được trả về bởi ValidationError. Không quan trọng đối với trường hợp sử dụng của bạn, bạn có thể bỏ nó ra.

Xem, regex do tôi đề xuất sẽ cho phép bất kỳ ký tự nào bao gồm khoảng trắng. Để chỉ cho phép các ký tự chữ và số, hãy thay thế '.' với '\ w' trong đối số regex. Đối với các yêu cầu khác, ReadTheDocs;).

+0

+1 có vẻ như là một giải pháp tốt, nhưng hãy giải thích cách sử dụng nó;) – supervacuo

+0

@supervacuo Tôi vừa chỉnh sửa nó để làm cho nó trở thành một câu trả lời hoàn chỉnh hơn. Cảm ơn đề xuất của bạn. Tôi thường có một cách tiếp cận nhỏ gọn :). – tBuLi

+6

thích câu trả lời được chấp nhận này vì nó đảm bảo độ dài chính xác ngay cả khi người dùng không sử dụng VolumeForm –

32

Loại cùng dòng như trên, nhưng đối với những gì nó có giá trị bạn cũng có thể đi trước với MinLengthValidator mà django cung cấp. Đã làm cho tôi. Mã sẽ trông giống như sau:

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

Đây là câu trả lời hay nhất. –

+1

Câu trả lời đúng! https://docs.djangoproject.com/en/1.11/ref/validators/#minlengthvalidator – Raptor

Các vấn đề liên quan