2013-08-22 14 views
18

Rozważ następujące ModelAdmin. W tym przypadku chciałbym mieć wbudowany interfejs "Book" między zestawem pól "None" i zestawem pól Notes. Czy to jest możliwe?Jak wyświetlić model wbudowany administratora Django w zestawie pól?

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

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

Odpowiedz

6

Niestety nie jest to możliwe z (standardowy szablon z) django. Jeśli spojrzeć na szablonie dla change_form, można zobaczyć, że inlines są zawsze renderowane oddzielnie po zestaw pól: https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html

Jedyne obejście widzę jest napisanie własnego szablonu względem kolejności.

+3

Innym obejściem, które jest czystsze pod niektórymi względami - i bardziej brudne w innych - byłoby użycie jQuery do przeniesienia inline. –

+1

@andybak biorąc pod uwagę obecne ograniczenie, użycie jquery byłoby czystym rozwiązaniem. – elsadek

+0

Możesz również utworzyć zestaw pól dla samego wiersza, jeśli nie jest on częścią zestawu pól nadrzędnych. Właśnie to było po mnie. – radtek

9

Bertrand Bortage pisał inne rozwiązanie tutaj: https://groups.google.com/forum/#!topic/django-users/yUq2Nvx_4eM

Późne odpowiedź powiedzieć, że po prostu popchnął dość czyste rozwiązanie tego problemu w jednym z moich projektów: https://github.com/dezede/dezede/commit/ed13ccaf34494e71fd913fd785c229052f6acdc8.

Chodzi o to, aby określić fieldsets_and_inlines_order w ModelAdmin (i), iterowalny od „f” i „I” znaków (dla „zestawu konkretną” i „inline”), która określa kolejność pomiędzy pierwszym fieldsets i w liniach. Jeśli len (fieldsets_and_inlines_order) < len (zestawy pól) + len (inlines), pozostałe to zachowanie oryginalne (najpierw zestawy pól , a następnie wszystkie inlines).

Przykład: trzeba 5 fieldsets i 3 inlines, określanie fieldsets_and_inlines_order = ('F', 'f', 'i', 'f', 'I') daje: fieldset fieldset rolki fieldset rolki fieldset fieldset inline Hope pomaga, Bertrand

Miałem inny pomysł, który jest warty rozważenia. Stwórz pole wypełniacza tylko do odczytu w zestawach pól dla każdego wstawianego, a następnie użyj jQuery, aby przesunąć inlines na miejsce dla każdego elementu zastępczego. Coś takiego (jQuery pominięty, ponieważ nie zostały jeszcze napisane go):

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 

jeszcze jedno - nie jest to kwestia otwarta Django prośbą o tym pozycjonowaniu inlines: https://code.djangoproject.com/ticket/4848

0

mam zupełnie inny skonstruowanej rozwiązanie generic ...

W swojej admin.py dodać nowe pole do Inline:

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

Następnie dostosować render_change_form z AdminClas s od modelu, który posiada 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) 

Posuwamy wszystkie inlines z dodatkowym polu pod własnym słownika z nazwy pola jako klucza ... ona być renderowane poprawnie utworzyć plik/templates/admin/includes/fieldset.html, który zastępuje standardowy zestaw pól django.html z następującej treści:

{% 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>

Spowoduje to dodanie posortowane inlines po odpowiednim polu ... Teraz trzeba tylko custom_filter do pracy ze słownikiem w szablonie django, tworzyć templatetags/custom_filter. py i dodać:

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

i voila: można wprowadzić dowolną fieldName do dowolnego Inline dodać go po tej dziedzinie ... jest to praca nieco w konfiguracji, ale jeśli masz kilka inlines do sortowania może być czystszy sposób ...

Powiązane problemy