2013-08-22 46 views
18

Xem xét ModelAdmin sau. Trong trường hợp này, tôi muốn hiển thị giao diện người dùng "Sách" nội tuyến giữa trường "Không có" và trường ghi chú Ghi chú. Điều đó có thể không?Làm cách nào để hiển thị mô hình nội tuyến quản trị Django trong một fieldset?

class AuthorAdmin(admin.ModelAdmin): 
    inlines = [BookInline] 

    fieldsets = (
      (None, { 
       'fields': ('author_name', 'date_of_birth') 
      }), 
      ('Notes', { 
       'fields': (['notes']) 
      }), 
    ) 

Trả lời

6

Thật không may điều này là không thể với (mẫu chuẩn từ) django. Nếu bạn xem mẫu cho change_form, bạn có thể thấy rằng nội tuyến luôn được hiển thị riêng sau khi fieldset: https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html

Cách duy nhất tôi thấy là viết mẫu tùy chỉnh theo thứ tự bạn muốn.

+3

Một cách giải quyết khác gọn gàng hơn trong một số trường hợp - và bẩn hơn ở những người khác - sẽ sử dụng jQuery để di chuyển nội tuyến. –

+1

@andybak với giới hạn hiện tại, sử dụng jquery sẽ là một cách giải quyết rõ ràng. – elsadek

+0

Bạn cũng có thể tạo fieldset cho chính nội tuyến, nếu nó không phải là một phần của bộ trường gốc. Đó là những gì tôi đã được sau khi anyways. – radtek

9

Bertrand Bortage posted giải pháp khác ở đây: https://groups.google.com/forum/#!topic/django-users/yUq2Nvx_4eM

Câu trả lời muộn để nói rằng tôi chỉ đẩy một giải pháp khá sạch cho vấn đề này tại một trong những dự án của tôi: https://github.com/dezede/dezede/commit/ed13ccaf34494e71fd913fd785c229052f6acdc8.

Ý tưởng là để xác định fieldsets_and_inlines_order trong ModelAdmin của bạn (s), một iterable của 'f' và 'i' ký tự (ví "fieldset" và "inline") mà xác định thứ tự giữa fieldsets đầu tiên và trong dòng. Nếu len (fieldsets_and_inlines_order) < len (fieldsets) + len (nội tuyến), phần còn lại theo hành vi ban đầu (các trường trước, sau đó tất cả nội tuyến).

Ví dụ: bạn có 5 fieldsets và 3 inlines định fieldsets_and_inlines_order = ('f', 'f', 'i', 'f', 'i') sẽ cung cấp cho bạn: fieldset fieldset inline fieldset inline fieldset fieldset inline Hope nó giúp, Bertrand

Tôi có một ý tưởng đáng xem xét. Tạo một trường phần giữ chỗ chỉ đọc trong các trường của bạn cho mỗi nội tuyến sau đó sử dụng jQuery để di chuyển các dòng vào vị trí cho mỗi trình giữ chỗ. Một cái gì đó như thế này (jQuery bỏ qua như tôi đã không viết nó chưa):

fieldsets = (
     (None, { 
      'fields': (
       ('inline_images',) 
       ('thumbnail_image',), 
       ('inline_authors',) 
       ('title', 'is_active', 'order',) 
      ), 
     }), 
    ) 

readonly_fields = ('inline_images', 'inline_authors') 

inline_images = '<span id='replaceme inline_images'></span>' 
inline_images.allow_tags = True 
inline_authors = '<span id='replaceme inline_authors'></span>' 
inline_authors.allow_tags = True 

Một điều nữa - có một vấn đề Django ngỏ yêu cầu vị trí này của inlines: https://code.djangoproject.com/ticket/4848

0

tôi đã xây dựng khác khá giải pháp chung chung ...

trong admin.py bạn thêm một lĩnh vực mới để Inline của bạn:

class YourModelInline(admin.TabularInline): 
    model = YourModel 
    after_field = "fieldname_of_field_before_inline" 

Sau đó tùy chỉnh render_change_form của AdminClas s của mô hình chứa Inline:

class EditModelAdmin(model.ModelAdmin): 
    inlines = [YourModelInline,] 

    def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): 
     sorted_inline_formsets = {} 
     inline_admin_formsets = context['inline_admin_formsets'] 
     formsets_to_remove = [] 

     for inline_formset in inline_admin_formsets: 
      if hasattr(inline_formset.opts, 'after_field'): 
       fieldname = inline_formset.opts.after_field 
       if fieldname in sorted_inline_formsets: 
        sorted_inline_formsets[fieldname].append(inline_formset) 
       else: 
        sorted_inline_formsets.update({ 
         fieldname: [inline_formset,] 
        }) 
       formsets_to_remove.append(inline_formset) 
     for inline_formset in formsets_to_remove: 
      inline_admin_formsets.remove(inline_formset) 

     context.update({ 
      'sorted_inline_formsets': sorted_inline_formsets, 
      'inline_admin_formsets': inline_admin_formsets 
     }) 
     return super(EditModelAdmin, self).render_change_form(request, context, add=add, 
                 change=change, obj=obj, form_url=form_url) 

Chúng tôi đang di chuyển tất cả inlines với trường bổ sung vào từ điển riêng với fieldname như chìa khóa ... Đối với nó để được trả lại một cách chính xác tạo tập tin/templates/admin/includes/fieldset.html ghi đè fieldset django chuẩn.html với nội dung sau:

{% load custom_filter %} 
 
<fieldset class="module aligned {{ fieldset.classes }}"> 
 
     {% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %} 
 
     {% if fieldset.description %} 
 
      <div class="description">{{ fieldset.description|safe }}</div> 
 
     {% endif %} 
 
     {% for line in fieldset %} 
 
      <div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}"> 
 
       {% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %} 
 
       {% for field in line %} 
 
        <div{% if not line.fields|length_is:'1' %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}> 
 
         {% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %} 
 
         {% if field.is_checkbox %} 
 
          {{ field.field }}{{ field.label_tag }} 
 
         {% else %} 
 
          {{ field.label_tag }} 
 
          {% if field.is_readonly %} 
 
           <div class="readonly">{{ field.contents }}</div> 
 
          {% else %} 
 
           {{ field.field }} 
 
          {% endif %} 
 
         {% endif %} 
 
         {% if field.field.help_text %} 
 
          <div class="help">{{ field.field.help_text|safe }}</div> 
 
         {% endif %} 
 
        </div> 
 
        {% if field.field.name %} 
 
         {% with field.field.name as fieldname %} 
 
          {% if sorted_inline_formsets|get_dict_value:fieldname != False %} 
 
           {% for inline_admin_formset in sorted_inline_formsets|get_dict_value:fieldname %} 
 
            {% include inline_admin_formset.opts.template %} 
 
           {% endfor %} 
 
          {% endif %} 
 
         {% endwith %} 
 
        {% endif %} 
 
       {% endfor %} 
 
      </div> 
 
     {% endfor %} 
 
    </fieldset>

này sẽ thêm inlines được sắp xếp sau khi lĩnh vực tương ứng ... Bây giờ bạn chỉ cần custom_filter để làm việc với từ điển trong mẫu django, tạo templatetags/custom_filter. py và thêm:

@register.filter 
def get_dict_value(dict, key): 
    if key in dict: 
     return dict[key] 
    else: 
     return False 

và thì đấy: bạn có thể nhập bất kỳ fieldname vào bất kỳ Inline để thêm nó sau khi lĩnh vực mà ... đó là một công việc chút để thiết lập nhưng nếu bạn có một vài inlines để sắp xếp nó có thể là một cách sạch hơn ...

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