2011-01-12 30 views
11

Tôi có một mô hình trông giống như:Thêm trường để Django ModelForm mà không phải là trong mô hình

class MySchedule(models.Model): 
    start_datetime=models.DateTimeField() 
    name=models.CharField('Name',max_length=75) 

Với nói ModelForm của nó:

class MyScheduleForm(forms.ModelForm): 
    startdate=forms.DateField() 
    starthour=forms.ChoiceField(choices=((6,"6am"),(7,"7am"),(8,"8am"),(9,"9am"),(10,"10am"),(11,"11am"), 
     (12,"noon"),(13,"1pm"),(14,"2pm"),(15,"3pm"),(16,"4pm"),(17,"5pm"), 
     (18,"6pm" 
    startminute=forms.ChoiceField(choices=((0,":00"),(15,":15"),(30,":30"),(45,":45")))),(19,"7pm"),(20,"8pm"),(21,"9pm"),(22,"10pm"),(23,"11pm"))) 

    class Meta: 
    model=MySchedule 

    def clean(self): 
    starttime=time(int(self.cleaned_data.get('starthour')),int(self.cleaned_data.get('startminute'))) 
    return self.cleaned_data 

    try: 
    self.instance.start_datetime=datetime.combine(self.cleaned_data.get("startdate"),starttime) 

    except TypeError: 
    raise forms.ValidationError("There's a problem with your start or end date") 

Về cơ bản, tôi đang cố gắng để phá vỡ trường DateTime trong mô hình thành 3 trường biểu mẫu có thể sử dụng dễ dàng hơn - bộ chọn ngày, danh sách thả xuống một giờ và menu thả xuống một phút. Sau đó, một khi tôi đã nhận được ba đầu vào, tôi tập hợp lại chúng thành một DateTime và lưu nó vào mô hình.

Một số câu hỏi:

1) Đây có phải là cách sai lầm để thực hiện? Tôi không muốn tạo ra các trường trong mô hình cho giờ, phút, vv, vì đó là tất cả về cơ bản chỉ là dữ liệu trung gian, vì vậy tôi muốn một cách để phá vỡ trường DateTime thành các trường con.

2) Khó khăn mà tôi đang gặp phải là khi trường bắt đầu trống - có vẻ như nó không bao giờ được kiểm tra không trống và chỉ kết thúc bằng cách ném lên một TypeError sau khi chương trình mong đợi một ngày và được Không. Django kiểm tra đầu vào trống ở đâu và tăng lỗi cuối cùng quay trở lại biểu mẫu? Đây có phải là trách nhiệm của tôi không? Nếu vậy, làm thế nào để tôi làm điều đó, vì nó không đánh giá clean_startdate() kể từ khi startdate không có trong mô hình.

3) Có cách nào tốt hơn để thực hiện việc này với kế thừa không? Có lẽ kế thừa MyScheduleForm trong BetterScheduleForm và thêm các trường ở đó? Làm thế nào tôi sẽ làm điều này? (Tôi đã chơi đùa với nó trong hơn một giờ và dường như không thể có được nó)

Cảm ơn!

[Edit:] Còn lại ngoài khơi self.cleaned_data trở lại - mất nó trong sao chép/dán ban đầu

+0

Nói chung, ModelForm có thể chứa bất kỳ trường nào bạn muốn. Nó giống như một Form bình thường trong vấn đề đó. Mối quan tâm duy nhất là bạn sẽ cần phải thực hiện dữ liệu ban đầu, các phương thức clean() thích hợp và phương thức save() thích hợp nếu các trường đó không tồn tại trong mô hình, vì ModelForm cố gắng tạo ra những thứ tự động sử dụng một cách kỳ diệu ngươi mâu. Yêu cầu – Cerin

Trả lời

0

1: Tôi không nghĩ rằng đó là sai lầm, bởi vì bạn có một số nội dung rất cụ thể diễn ra ở đó:

  • mục thời gian cụ thể (trưa, kết thúc tại 5:00 ..) increments
  • 15 phút cho startminutes

2: cập nhật: bình luận dưới đây cho biết lĩnh vực của bạn nên được required=True theo mặc định. Đó là sự thật, bạn sẽ nhận được một ValidationError với biểu mẫu của bạn nếu trường này được để trống.

Bạn có thể đăng TypeError bạn đang nói về không? Có phải nó đang xảy ra bên ngoài khối clean() không? Bởi vì nếu bạn không trả lại cleaned_data từ chức năng sạch của bạn như trong ví dụ của bạn, biểu mẫu của bạn sẽ không có bất kỳ dữ liệu nào để làm việc ngay cả khi ban đầu nó kiểm tra bằng cách không tăng bất kỳ ValidationErrors.

Dù sao, bạn có thể khám phá các phương pháp clean_ cho mỗi xác thực trường.

def clean_startdate(self): 
    if not self.cleaned_data['startdate']: 
      raise forms.ValidationError("Must enter a start date") 

http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-clean-method

3: Bạn có thể làm rõ ở đây những gì bạn đang cố gắng để làm với thừa kế? Có vẻ như định nghĩa trường của bạn rất cụ thể đối với biểu mẫu này, vì vậy nó thuộc về ngay tại đây trong số MyScheduleForm.Thừa kế là để sử dụng lại mã:)

Nếu bạn đang tìm cách sử dụng lại mã này cho nhiều DateTimeField, bạn có thể sử dụng kế thừa biểu mẫu. Bạn có thể định nghĩa một ModelForm như bạn có bây giờ, phân lớp nó, và ghi đè của Meta mẹ như thể hiện ở đây trong các tài liệu để sử dụng nó trên nhiều mô hình: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#form-inheritance

Tôi cũng muốn kiểm tra như thế nào django không SplitDateTimeWidget của nó (kiểm tra nguồn): http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.SplitDateTimeWidget

Có một số tiện ích con ngày phân chia 'bên thứ ba' khác đáng xem xét trên mạng nội bộ!

+0

= True là cài đặt mặc định cho các trường biểu mẫu django. –

+0

Điểm tốt, nhưng sau đó anh ta không nên gặp vấn đề với # 2. Tôi tự hỏi tại sao trường đó không xác nhận? hmm –

+0

Cảm ơn phản hồi của bạn - dưới đây là một vài câu trả lời cho câu hỏi của bạn: 1) Tôi biết rằng mặc định là bắt buộc = True. Vấn đề là, nếu các trường không mô hình (startdate, starthour, vv) được để trống, nó không ném một ngoại lệ và trả về thông tin "trường bị thiếu" vào biểu mẫu của tôi. Tôi muốn nó kiểm tra trống và balk nếu có một trường trống, nhưng nó dường như bỏ lỡ điều này cho đến khi trường trống gây ra vấn đề sau trong sạch() 2) Tôi đã thử thêm một hàm clean_startdate(), nhưng có vẻ như không bao giờ được gọi. Tuy nhiên, các hàm clean_ cho các trường trong mô hình DO của tôi được gọi. – Cyclic

1
  1. Nếu tôi là bạn, tôi đã sử dụng số customised Django-admin date/time widget(s) để nhập ngày/giờ.

  2. Về hình thức xác nhận, hãy chắc chắn bạn vượt qua các hình thức liên quan đến việc yêu cầu cho nó xuất hiện lỗi dựa theo mẫu. (Mã mẫu bên dưới)

  3. Đối với việc sử dụng thừa kế, nó sẽ là quá mức cần thiết cho trường hợp sử dụng này vì nó sẽ không phục vụ bất kỳ mục đích nào và tốt hơn là giữ mọi thứ đơn giản.

Mẫu mã:

if request.POST: 
    form = MyScheduleForm(request.POST) 
    if form.is_valid(): 
     # Specific stuff with the variables here 
     pass 
else: 
    form = MyScheduleForm() 
+0

Vâng, tôi đang sử dụng một cấu trúc tương tự. Vấn đề là các trường phi mô hình dường như không bao giờ được kiểm tra để xem chúng có trống không, vì vậy nếu chúng trống, chúng không ném một ngoại lệ. Các trường trong mô hình DO được kiểm tra và tôi nhận được một lỗi được chuyển lại cho biểu mẫu của tôi nếu chúng thiếu – Cyclic

+0

Có nhiều trường hợp đáp ứng mắt. Tôi có thể chạy mã trên và nó được xác nhận! –

0

Đối với các trường hình thức mà có thể chứa các giá trị trống, bạn phải khai báo lĩnh vực này như sau:

start_datetime=models.DateTimeField(blank=True, null=True) 

này kể về hình thức mà nó có thể được blank và trường cơ sở dữ liệu có thể là null. Điều đó có thể khắc phục vấn đề đó.

Tại sao bạn đang sử dụng một ModelForm nếu bạn đang cố gắng để bao gồm các lĩnh vực mà không phải là một phần của mô hình? ModelForms được thiết kế để tạo nhanh các biểu mẫu liên kết trực tiếp với mô hình của bạn. Tất nhiên họ có các tùy chỉnh khác nhau, nhưng thay đổi các lĩnh vực thực tế dường như với tôi một cái gì đó mà một hình thức thường xuyên là cho.

Nếu không, nếu bạn chỉ muốn chia VIEW của biểu mẫu, không phải là biểu mẫu, hãy tạo tiện ích tùy chỉnh để hiển thị trường Ngày giờ, chẳng hạn như SplitDateTimeWidget. Phân lớp nó và cung cấp CHOICES của bạn cho các giá trị của menu thả xuống.

+0

-1 nếu tôi muốn sử dụng hầu hết chức năng này và tùy chỉnh một chút thì sao? – Alvaro

+0

@Alvaro Tôi đã đề cập rằng trong câu trả lời của tôi. Có các móc nối cho một số tùy chỉnh nhất định, nhưng việc thêm nhiều trường biểu mẫu không ánh xạ tới các trường mô hình là * không * các biểu mẫu mô hình là gì. –

1

Ok, tôi nghĩ rằng tôi figured it out:

Tính đến Django 1.2, chạy is_valid() gây nên xác nhận MODEL trên ModelForms. Tôi đã giả định rằng các trường sẽ được kiểm tra cho các giá trị trống trước khi nhấn sạch() chức năng mô hình, vì vậy chức năng làm sạch của tôi không kiểm tra cho các giá trị trống hoặc Không loại. Về cơ bản, mẫu clean() của tôi trông giống như sau:

def clean(self): 
    if self.start_datetime > datetime.now(): 
     raise ValidationError('Start date can\'t be in the future') 

Vì vậy, tôi cho rằng chủ yếu là trả lời câu hỏi của tôi. câu hỏi Tuy nhiên, tôi đã 1 còn lại:

Là nó tốt nhất để kiểm tra giá trị trống trong mô hình sạch(), hoặc là có một cách tốt hơn để làm điều này? Có vẻ hackish để kiểm tra các khoảng trống trong mô hình thay vì trong ModelForm - là xác nhận trên các lĩnh vực hình thức phải thiếu đầu vào cờ trên trường bắt buộc?

Cảm ơn sự giúp đỡ của mọi người.

+0

Chắc chắn sử dụng các phương thức 'clean_field' trên' ModelForm'. Tôi rất bối rối vì khi tôi tạo lại biểu mẫu của bạn, tôi nhận được một 'ValidationError' cho các trường bổ sung được thêm vào ModelForm của tôi. Tôi tạo ra một ModelForm, thêm một phương pháp sạch giống như của bạn, và Validation kích hoạt .. Có gì khác để ModelForm của bạn hơn bạn đã hiển thị? –

+0

Tôi nghĩ rằng vấn đề ở đây (sau khi rối tung xung quanh với nó) - nếu trường trống, nó không bao giờ được thêm vào clean_data, và phương thức clean_field không bao giờ chạy. Sau đó nó chạy biểu mẫu sạch() và mô hình sạch(). Trong trường hợp của tôi, mô hình clean() gây ra một ngoại lệ TypeError do so sánh tôi đã thực hiện trong sạch(), khiến mã của tôi thất bại. Tôi nghĩ vấn đề này ở đây (sửa tôi nếu tôi sai) - giá trị trống không kích hoạt ngoại lệ, chúng chỉ gây ra is_valid() thất bại và chúng thêm lỗi vào error_list. Vì tôi đã có một lỗi khác (mà thực sự DID ném một excpt), điều đó gây ra vấn đề của tôi – Cyclic

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