2010-10-14 40 views
6

Cho một lớp mẫu (ở đâu đó sâu trong ứng dụng Django khổng lồ của bạn) ..Khỉ vá một lớp biểu mẫu Django?

class ContactForm(forms.Form): 
    name = ... 
    surname = ... 

Và xem xét mà bạn muốn thêm lĩnh vực khác để hình thức này mà không mở rộng hoặc sửa đổi các lớp hình thức tự, tại sao không cách tiếp cận sau đây hoạt động?

ContactForm.another_field = forms.CharField(...) 

(đoán đầu tiên của tôi là hackery metaclass rằng Django sử dụng chỉ áp dụng cho lần đầu tiên lớp mẫu được xây dựng. Nếu vậy, sẽ có thể là một cách để redeclare lớp để khắc phục điều này?)

+0

Bạn gần như chắc chắn đúng. Đây chính xác là lý do bạn không thể dễ dàng thêm các trường mới vào một lớp con mô hình.Model. –

+0

Với các mô hình có sự cố "syncdb" ngay cả khi việc vá khỉ hoạt động. Nhưng với hình thức vá khỉ có thể là một người tiết kiệm cuộc sống tại một số thời điểm IMHO. –

Trả lời

7

Một số định nghĩa thích hợp xảy ra trong django/forms/forms.py. Đó là:

  1. class BaseForm
  2. class Form
  3. class DeclarativeFieldsMetaclass
  4. def get_declared_fields

get_declared_fields được gọi từ DeclarativeFieldsMetaclass và xây dựng một danh sách với các trường hợp lĩnh vực được sắp xếp theo quầy sáng tạo của họ. Sau đó nó sẽ thêm các trường từ các lớp cơ sở vào danh sách này và trả về kết quả dưới dạng một cá thể OrderedDict với tên trường đóng vai trò là các khóa. DeclarativeFieldsMetaclass sau đó dán giá trị này vào thuộc tính base_fields và gọi tới type để tạo lớp. Sau đó, nó chuyển lớp tới hàm media_property trong widgets.py và gắn giá trị trả về cho thuộc tính media trên lớp mới.

media_property trả về phương thức thuộc tính để tạo lại các khai báo phương tiện trên mọi truy cập. Cảm giác của tôi là nó sẽ không có liên quan ở đây nhưng tôi có thể sai.

Ở bất kỳ mức nào, nếu bạn không khai báo thuộc tính Media (và không có lớp cơ sở nào) thì nó chỉ trả về trường hợp Media mới không có đối số cho hàm tạo và tôi cho rằng đơn giản như chèn trường theo cách thủ công vào base_fields.

ContactForm.another_field = forms.CharField(...) 
ContactForm.base_fields['another_field'] = ContactForm.another_field 

Mỗi hình thức ví dụ sau đó nhận được một deepcopy của base_fields đó trở thành form_instance.fields trong phương pháp __init__ của BaseForm. HTH.

+0

Cảm ơn rất nhiều. Dường như làm việc như một say mê. –

+0

+1 Điểm đến OrderedDict dẫn tôi đến SortedDict. Không chắc chắn sự khác biệt là gì, nhưng cả hai đều làm việc cho vấn đề của tôi (không biết về OP). Cảm ơn. – jrhorn424

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