2009-02-06 35 views
34

Tôi biết bạn có thể chỉ định các trường trong django cho người trợ giúp quản trị. Tuy nhiên, tôi không thể tìm thấy bất cứ điều gì hữu ích cho ModelForms. Chỉ một số bản vá mà tôi không thể sử dụng. Tui bỏ lỡ điều gì vậy? Có cách nào tôi có thể đạt được một cái gì đó giống như các lĩnh vực mà không cần viết ra từng trường trên mẫu của tôi theo cách thủ công trong thẻ thích hợp.Django và các trường trên ModelForm

Tôi lý tưởng muốn lặp qua một tập hợp các BoundFields. Tuy nhiên, thực hiện một việc như thế này ở cuối ModelForm của tôi:

fieldsets = [] 
    fieldsets.append(('Personal Information', 
         [username,password,password2,first_name,last_name,email]),) # add a 2 element tuple of string and list of fields 
    fieldsets.append(('Terms & Conditions', 
         [acceptterms,acceptprivacy]),) # add a 2 element tuple of string and list of fields 

không thành công vì các mục chứa trong cấu trúc dữ liệu của tôi là các trường thô, không phải là BoundFields. T trông giống như BoundFields được tạo ra trên bay ... điều này làm cho tôi buồn. Tôi có thể tạo lớp con của riêng tôi của forms.Form trong đó có một khái niệm về fieldsets (thậm chí là một rough mà không phải là tương thích ngược ... điều này chỉ dành cho dự án của riêng tôi) và nếu như vậy, bạn có thể cung cấp cho bất kỳ con trỏ? Tôi không muốn gây rối với mã django.

Trả lời

34

Các trường trong mô hình vẫn ở trong giai đoạn "thiết kế". Có một số ticket ở Django trac với hoạt động thấp.

Đó là điều tôi đã quan tâm đến việc nghiên cứu bản thân mình trong tương lai gần, nhưng kể từ khi tôi đã không làm được điều đó nhưng các tốt nhất mà tôi có thể cung cấp được những đoạn:

Edit: tôi chỉ nhận thấy câu hỏi này một lần nữa và tôi lại alize nó cần một chỉnh sửa để chỉ ra dự án của Carl django-form-utils trong đó có một lớp BetterForm có thể chứa các fieldets. Nếu bạn thích dự án này, hãy cung cấp cho anh ấy +1 câu trả lời của mình bên dưới :)

+1

Các liên kết thứ hai đã cho tôi manh mối rằng tôi cần phải thực hiện hỗ trợ fieldset thô sơ của tôi. Cảm ơn bạn. –

+1

tháng 11 năm 2010, sử dụng thành công django-form-utils với 1.2.3. Cảm ơn gợi ý. – Boldewyn

16

Một điều bạn có thể làm là chia các trường logic thành các lớp biểu mẫu mô hình riêng biệt.

class PersonalInfoForm (forms.ModelForm): 
    class Meta: 
     model=MyModel 
     fields=('field1', 'field2', ...) 

class TermsForm (forms.ModelForm): 
    class Meta: 
     model=MyModel 
     fields=('fieldX', 'fieldY', ...) 

Vượt qua họ cho mẫu của bạn trong các biến khác nhau và chia tay các formsets:

<form ...> 
    <fieldset><legend>Personal Information</legend> 
     {{ personal_info_form }} 
    </fieldset> 
    <fieldset><legend>Terms and Conditions</legend> 
     {{ terms_form }} 
    </fieldset> 
</form> 

Theo nghĩa rằng mỗi lớp form của bạn chỉ là một mảnh vỡ của mẫu HTML thực tế.

Nó giới thiệu một liên lạc phức tạp khi bạn gọi lưu trên biểu mẫu. Có thể bạn sẽ muốn vượt qua commit = False và sau đó hợp nhất các đối tượng kết quả. Hoặc chỉ cần tránh sử dụng ModelForm.save hoàn toàn và điền vào đối tượng mô hình của bạn bằng tay với 'cleaned_data'

+1

Đây là nỗ lực quá nhiều, đặc biệt là trong lớp xem. – Greg

+3

@Greg, Downvote không làm phiền tôi, nhưng bình luận của bạn là khó hiểu. Bạn có ý gì bởi nỗ lực quá nhiều? Phá vỡ một hình thức nguyên khối thành các mảnh hình thức riêng biệt mà bạn có thể thao tác độc lập với nhau là một cách tiếp cận thành ngữ cho vấn đề này. Django có thể đã thêm nhiều tiện ích "fieldset" hơn trong hai năm kể từ khi tôi cung cấp câu trả lời này, nhưng cách tiếp cận vẫn hợp lệ. –

+1

Quan điểm của Greg là khủng khiếp không hợp lệ! .. Tùy chọn này được áp dụng và linh hoạt. Thời gian duy nhất nó không hoạt động, là khi trong phương pháp 'sạch', một số dữ liệu từ hai hoặc nhiều trường mẫu có thể được yêu cầu! – StefanNch

50

Tôi nghĩ rằng this snippet thực hiện chính xác những gì bạn muốn. Nó cung cấp cho bạn một lớp con biểu mẫu cho phép bạn khai báo một cách rõ ràng biểu mẫu của bạn thành các trường và lặp qua chúng trong mẫu của bạn.

Cập nhật: đó là đoạn mã có kể từ khi trở thành một phần của django-form-utils

+0

Tuyệt vời, nó đang diễn ra trong dự án hiện tại của tôi! –

+0

Cảm ơn django-form-utils! Làm việc như một say mê. – Boldewyn

+0

Tôi đang sử dụng hình thức-utils là tốt, và tôi cũng đã viết một phần mở rộng cho form-utils cho phép các trường được sắp xếp theo hàng trong fieldset .. giống như admin. Tôi đang lên kế hoạch liên lạc với tác giả của form-utils để xem liệu anh ta có chấp nhận nó như là một bản vá hay không. Trong khi đó, nếu bạn muốn, chỉ cần hỏi ... –

0

Đây là mã mà tôi đã phát triển để hiểu các thẻ tùy chỉnh (có liên kết). Tôi đã áp dụng nó để tạo một fieldset.

Tuyên bố từ chối trách nhiệm: Tôi khuyến khích sử dụng bất kỳ câu trả lời nào ở trên, đây chỉ là vì lợi ích của việc học.

templatetags/myextras.py:

from django import template 
from django.template import Context 

register = template.Library() 


class FieldsetNode(template.Node): 
    """ Fieldset renderer for 'fieldset' tag """ 
    def __init__(self, nodelist, fieldset_name): 
     """ Initialize renderer class 
     https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-renderer 
     :param nodelist: a list of the template nodes inside a block of 'fieldset' 
     :param fieldset_name: the name of the fieldset 
     :return: None 
     """ 
     self.nodelist = nodelist 
     self.fieldset_name = fieldset_name 

    def render(self, context): 
     """ Render the inside of a fieldset block based on template file 
     https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#auto-escaping-considerations 
     :param context: the previous template context 
     :return: HTML string 
     """ 
     t = context.template.engine.get_template('myapp/fieldset.html') 
     return t.render(Context({ 
      'var': self.nodelist.render(context), 
      'name': self.fieldset_name, 
     }, autoescape=context.autoescape)) 


@register.tag 
def fieldset(parser, token): 
    """ Compilation function for fieldset block tag 
    Render a form fieldset 
    https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-compilation-function 
    https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#parsing-until-another-block-tag 
    :param parser: template parser 
    :param token: tag name and variables 
    :return: HTML string 
    """ 
    try: 
     tag_name, fieldset_name = token.split_contents() 
    except ValueError: 
     raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0]) 
    if not (fieldset_name[0] == fieldset_name[-1] and fieldset_name[0] in ('"', "'")): 
     raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name) 
    nodelist = parser.parse(('endfieldset',)) 
    parser.delete_first_token() 
    return FieldsetNode(nodelist, fieldset_name[1:-1]) 

templates/myapp/fieldset.html:

<div class="fieldset panel panel-default"> 
    <div class="panel-heading">{{ name }}</div> 
    <div class="panel-body">{{ var }}</div> 
</div> 

templates/myapp/myform.html:

<form action="{% url 'myapp:myurl' %}" method="post"> 
    {% csrf_token %} 
    {% fieldset 'General' %} 
     {{form.myfield1 }} 
    {% endfieldset %} 
    {# my submit button #} 
</form> 
Các vấn đề liên quan