2010-01-22 59 views
31

我定義了幾種模式:期刊,卷volume_scanInfo等Django的InlineModelAdmin:顯示部分內嵌模型,並鏈接到完整的模型

一本期刊可以有更多的容量和體積可以有更多的scanInfo。

我想要做的是:

    在期刊的管理頁面
  • 我想有卷內聯(完成)的列表
  • 前面列表中的每個卷連接到其管理頁面在那裏我可以顯示錶單來編輯內容的「掃描信息」列表和內聯列表。

,所以我想有這樣的:

Journal #1 admin page 
[name] 
[publisher] 
[url] 
..... 
list of volumes inline 
    [volume 10] [..(other fields)..] <a href="/link/to/volume/10">Full record</a> 
    [volume 20] [..(other fields)..] <a href="/link/to/volume/20">Full record</a> 

然後

Volume #20 admin page 
[volume number] 
[..(other fields)...] 
...... 
list of the scan info inline 
    [scan info 33] [..(other fields)..] <a href="/link/to/scaninfo/33">Full record</a> 
    [scan info 44] [..(other fields)..] <a href="/link/to/scaninfo/44">Full record</a> 

我試圖做的是定義一個創建代碼模型方法,並嘗試使用它裏面的在管理員中定義「內聯卷」的類,但它不起作用。

換句話說

模型 「卷」 有着內在的東西,如:

def selflink(self): 
    return '<a href="/admin/journaldb/volume/%s/">Full record</a>' % self.vid 
selflink.allow_tags = True 

class VolumeInline(admin.TabularInline): 
    fields = ['volumenumber', 'selflink'] 
    model = Volume 
    extra = 1 

但是,這提供了以下錯誤:

Exception Value: 'VolumeInline.fields' refers to field 'selflink' that is missing from the form. 

任何想法?

感謝, 喬瓦尼

+0

非常好的問題。這種功能應該內置。 – 2011-11-09 07:53:41

+0

iI內置。它在這裏回答(show_change_link)自django 1.8以來:http://stackoverflow.com/a/28170958/493272 – SpiRail 2016-05-19 21:48:46

+0

我知道,但問題是6歲: - ) 我會更新答案,所以很明顯有這個新功能。 – 2016-05-20 13:33:25

回答

29

UPDATE: 由於Django的1.8,這是建立在

this answerthe official documentation

OLD答:

最後我找到了一個簡單的解決方案。

我創建了一個名爲linked.html的新模板,它是tabular.html的副本,並添加了此代碼以創建鏈接。

{% if inline_admin_form.original.pk %} 
      <td class="{{ field.field.name }}"> 
       <a href="/admin/{{ app_label }}/{{ inline_admin_formset.opts.admin_model_path }}/{{ inline_admin_form.original.pk }}/">Full record</a> 
      </td> 
{% endif %} 

然後,我創建繼承InlineModelAdmin

#override of the InlineModelAdmin to support the link in the tabular inline 
class LinkedInline(admin.options.InlineModelAdmin): 
    template = "admin/linked.html" 
    admin_model_path = None 

    def __init__(self, *args): 
     super(LinkedInline, self).__init__(*args) 
     if self.admin_model_path is None: 
      self.admin_model_path = self.model.__name__.lower() 

的新模式LinkedInline然後當我定義了一個新的內嵌,我只有用我的LinkedInline而不是正常的InlineModelAdmin

我希望它對其他人有用。

喬瓦尼

+0

當您保存子模型頁面時,是否會回到父模型頁面? – 2011-11-09 07:47:33

+0

你是什麼意思? – 2011-11-30 10:19:44

+0

如果您正在編輯鏈接到日記帳的完整卷模型,那麼當您保存時,它會自動返回到日記本版本頁面嗎? – 2011-12-01 08:56:01

3

你試試Reversing admin URL系統?
,可以給類似的東西(在日記頁):

<ul> 
{% for volume in original.volume_set.all %} 
    <li> 
    <a href="{% url admin:yourapp_volume_change volume.id %}">Edit {{ volume }} 
    </a> 
    </li> 
{% endfor %} 
</ul> 
+0

+1,用於反轉管理URL的引用。 – rluba 2012-09-03 06:43:50

25

更新:

由於Django的1.8,這是現在built-in。 Django的< = 1.7

答:

保持你的代碼中models.py與有條件的情況下:

def selflink(self): 
    if self.id: 
     return "<a href='/link/to/volume/%s' target='_blank'>Edit</a>" % str(self.id) 
    else: 
     return "Not present" 

selflink.allow_tags = True 

admin.py,加selflink爲readonly領域:

class VolumeInline(admin.TabularInline): 
    readonly_fields = ['selflink',] 
    model = Volume 

這對我有效。

+3

如果您使用'fields'選項,則需要將它放在'readonly_fields'後面 – 2013-02-21 17:22:26

+1

@uszywieloryba:在Django-1.4.x中不真實。無論如何,'selflink'必須在'fields'或'fieldsets'中。 – Stan 2013-05-30 14:27:25

+0

我更喜歡在models.py中編寫代碼,而不是在temaplates中編寫代碼!謝謝 – Marconius 2013-06-04 15:21:55

2

經過一番搗亂之後,我可以使用reverse()在InlineAdmin和TabularInline中完成這項工作。至少有TabularInline,要鏈接必須在「readonly_fields」

# create a read-only inline with the first field linked 
from django.core import urlresolvers 
class YOUR_MODEL_Inline(LinkedTabularInline): 
    max_num = 0 # remove the "Add another ..." link 
    model = YOUR_MODEL_NAME 
    fk_name = "YOUR_FOREIGN_KEY_NAME" 
    fields = [ 'link_name', ] # , 'field1', 'field2', 'etc' ] 
    readonly_fields = fields 
    can_delete = False 
    def link_name(self, obj): 
     if obj.pk: 
      url = urlresolvers.reverse('admin:%s_%s_change' 
       % (obj._meta.app_label, obj._meta.module_name), args=[obj.id]) 
      # obj.MODEL_FIELD can be a text string or whatever you want 
      return '<a href="{0}">{1}</a>'.format(url, obj.MODEL_FIELD) 
    link_name.allow_tags = True 
    link_name.short_description = "MODEL_FIELD" 

如果你要鏈接到的變化列表,而不是更改視圖,您可以修改反向()調用上市現場。更改列表不需要對象ID。

url = urlresolvers.reverse('admin:%s_%s_changelist' 
     % (obj._meta.app_label, obj._meta.module_name)) 
    return '<a href="{0}">{1}</a>'.format(url, obj.name) 

如果你要鏈接到對象的一個​​子集,可以將網址添加參數:

return '<a href="{0}?YOUR_MODEL_FIELD__id__exact={1}">{2}</a>'.format(url, obj.id, obj.name) 
13

下面是基於一些其他的答案的可重複使用的混入。這很方便,因爲它可以同時處理Tabular和Stacked內聯,並且不會佔用您的模型或管理代碼。

# put this somewhere like admin_helpers.py 
from django.core.urlresolvers import reverse 

class InlineEditLinkMixin(object): 
    readonly_fields = ['edit_details'] 
    edit_label = "Edit" 
    def edit_details(self, obj): 
     if obj.id: 
      opts = self.model._meta 
      return "<a href='%s' target='_blank'>%s</a>" % (reverse(
       'admin:%s_%s_change' % (opts.app_label, opts.object_name.lower()), 
       args=[obj.id] 
      ), self.edit_label) 
     else: 
      return "(save to edit details)" 
    edit_details.allow_tags = True 

# admin.py 

class VolumeInline(InlineEditLinkMixin, admin.TabularInline): 
    fields = ['foo', 'bar', 'edit_details'] 

class JournalAdmin(admin.ModelAdmin): 
    inlines = [VolumeInline] 

class ScanInfoInline(InlineEditLinkMixin, admin.StackedInline): 
    fields = ['foo', 'bar', 'edit_details'] 

class JournalAdmin(admin.ModelAdmin): 
    inlines = [ScanInfoInline] 
+3

非常有幫助和整潔。我需要在代碼頂部添加這個'from django.core.urlresolvers import reverse' – Charlesliam 2014-01-24 03:02:37

+0

我想知道是否可以自動使用很多2個字段集合,在哪裏有'model = ModelA.modelbs.through'? 它需要檢測這個(也許通過'_meta.auto_created'?)並相應地創建編輯鏈接。 – blueyed 2014-06-20 00:36:16

8

Django 1.8+ this is now much easier。只需添加show_change_link = TrueTabularInlineStackedInline子類,像這樣:

class VolumeInline(admin.TabularInline): 
    fields = ['volumenumber'] 
    model = Volume 
    extra = 1 
    show_change_link = True 

而且Django會自動添加一個鏈接到充滿變化形式,每個聯項目,如果該模式有自己的註冊ModelAdmin

+0

現在應該接受回答 – 2016-11-13 03:14:55