2010-04-06 46 views
14

Tôi muốn tạo biểu mẫu bao gồm các trường từ hai mô hình riêng biệt, cùng với một số trường thông thường (không phải mô hình) khác. Biểu mẫu sẽ tạo một phiên bản của từng mô hình. Tôi không nghĩ rằng Tôi có thể sử dụng các biểu mẫu nội tuyến cho điều này vì tôi không muốn bao gồm tất cả các trường từ cả hai mô hình.Lấy trường biểu mẫu Django từ trường mô hình

Tôi muốn tạo trường biểu mẫu mà không cần mã hóa cứng loại trường mô hình.

Tôi biết tôi có thể lấy trường biểu mẫu từ trường mô hình bằng cách sử dụng model_field.formfield(). Nhưng làm thế nào tôi có thể nhận được trường mô hình cụ thể?

giải pháp đầu tiên của tôi:

def get_fields(model_class): 
    fields = {} 
    for f in model_class._meta.fields: 
     fields[f.name] = f 

class MyForm(forms.Form): 
    foo_name = get_fields(Foo)['name'].formfield() 
    bar_name = get_fields(Bar)['name'].formfield() 
    other_field = ... 

Có tương đương của get_fields chưa? Đây có phải là một ý tưởng tồi không? Tôi không thoải mái dựa vào mô hình thuộc tính _meta. Hoặc tôi đang đi về điều này một cách hoàn toàn sai?

+0

giải pháp của bạn nghe có vẻ hợp lý với tôi, altho, tôi không thấy lý do tại sao bạn không muốn cứng mã những 2 lĩnh vực; có lẽ bạn sẽ có được các mô hình động. –

+0

Tôi muốn tránh mã hóa cứng loại trường biểu mẫu trong trường hợp tôi đã từng thay đổi loại trường mô hình tương ứng. Bạn không chắc chắn về ý nghĩa của việc tạo mô hình động ...? – harto

Trả lời

14

Bạn cũng có thể xem django.forms.models.fields_for_model. Điều đó sẽ cung cấp cho bạn từ điển của các trường và sau đó bạn có thể thêm các trường của biểu mẫu

+0

Không nhận thấy phương pháp đó, cảm ơn. Đó là câu trả lời tôi đang tìm kiếm, nhưng có lẽ gợi ý của Casey Stark thích hợp hơn. – harto

11

Bạn không bao giờ phải tự xây dựng các trường trừ khi bạn muốn có một số hành vi đặc biệt.

Điều này phải đơn giản như sử dụng hai ModelForm s và thêm Form bên trong một thẻ <form> trong mẫu của bạn bằng một nút gửi.

trong forms.py:

class Model1Form(forms.ModelForm): 
    class Meta: 
     model = Model1 
     fields = ('fields', 'you', 'want') 

class Model2Form(forms.ModelForm): 
    class Meta: 
     model = Model2 
     fields = ('fields', 'you', 'want') 

class ExtraFieldsForm(forms.Form): 
    extra_field = form.TextField() # or whatever field you're looking for 

trong views.py:

form1 = Model1Form(request.POST or None) 
form2 = Model2Form(request.POST or None) 
form3 = ExtraFieldsForm(request.POST or None) 

if form1.is_valid() and form2.is_valid() and form3.is_valid(): 
    form1.save() 
    form2.save() 
    form3.save() 

    ...do other stuff like a redirect... 

và trong mẫu:

<form method="POST" action="">{% csrf_token %} 
    <fieldset> 
     {{ form1|as_uni_form }} 
     {{ form2|as_uni_form }} 
     {{ form3|as_uni_form }} 
     <div class="form_block"> 
      <input type="submit" value="Save both models"/> 
     </div> 
    </fieldset> 
</form> 

Tôi đang sử dụng để sử dụng django-uni- nhưng bạn có thể hiển thị các trường biểu mẫu theo ý muốn. Chúc may mắn với trang web của bạn.

+0

Tôi không sử dụng nhiều đối tượng 'Biểu mẫu' trong một phần tử'

'duy nhất. Cảm ơn đề nghị - Tôi sẽ cố gắng tối nay. – harto

+0

Tuyệt. Tôi hy vọng nó làm việc cho bạn. Tôi đã nhìn thấy nó được thực hiện trước nhưng điều này không được thử nghiệm. Bạn có thể cần phải chơi với logic xem để có được những gì bạn muốn. –

2

Một giải pháp khác có thể là tạo một biểu mẫu 'uber' tổng hợp các dạng mô hình cụ thể. Biểu mẫu này hỗ trợ các phương thức mà một biểu mẫu thường cung cấp và nó chuyển tiếp chúng tới tất cả các biểu mẫu con. Một số sẽ đơn giản, phức tạp khác. Ưu điểm lớn của cách tiếp cận đó là không có mã nào ngoài biểu mẫu bị ảnh hưởng (mã xác thực của khách hàng và giống nhau). Khái niệm này không thực sự mang tính cách mạng nhưng tôi cho là phức tạp để thêm vào sau đó. Paul

4

bây giờ là một documented API Có để nhận lĩnh vực mô hình từ một lớp mô hình:

my_model_field = MyModel._meta.get_field('my_model_field_name') 

Mặc dù nó không được chính thức ghi nhận cho đến khi Django 1.8, điều này sẽ làm việc với các phiên bản trước đó Django quá.

Khi bạn có điều này, bạn có thể lấy trường mẫu như vậy:

form_field = my_model_field.formfield() 
Các vấn đề liên quan