单对象管理页面,用于一对多对象

时间:2013-08-27 11:19:21

标签: python django

我有以下型号:

class Campaign:
    ...


class Location:
    ...
    campaign = models.ForeignKey(Campaign)

我通常会使用表格内联编辑位置,但由于位置数量非常高,我想将位置管理移动到另一个页面。它应该与普通管理员页面完全相同,除了它应该只显示所选广告系列的位置,并且在添加新位置时,它应自动附加到正确的广告系列。要访问“位置管理”页面,请点击“广告系列”列表中的链接。

这样做的正确方法是什么?还有其他选择吗?

1 个答案:

答案 0 :(得分:0)

您的问题没有开箱即用的解决方案,但这很容易做到。

我会将Locations注册为一个单独的模型管理对象,如下所示:

from django.contrib import admin
from models import Location

class LocationAdmin(EnhancedModelAdminMixin, admin.ModelAdmin):
    list_filter = 'campaign', 

admin.site.register(Location, LocationAdmin)

通过这种方式,您将拥有管理界面,您可以按广告系列过滤您的位置。

要直接访问Campaign模型管理员上的位置,我会使用https://github.com/charettes/django-admin-enhancer

在新的位置创建表单上自动选择已过滤的广告系列它有点棘手...但我的方法是添加查询参数到添加新位置按钮,然后在初始化创建表单时捕获它,以定义初始值野战活动。

首先创建一个模板,让我们说you_app / admin / change_list.html,如下所示:

{% extends "admin/change_list.html" %}
{% load i18n admin_static admin_list %}
{% load admin_urls %}

{% block object-tools %}
  {% if has_add_permission %}
    <ul class="object-tools">
      {% block object-tools-items %}
        <li>
          <a href="{% url cl.opts|admin_urlname:'add' %}{% if is_popup %}?_popup=1{% if selected_campaign %}&selected_campaign={{ selected_campaign }}{% endif %}
          {% elif selected_campaign %}?selected_campaign={{ selected_campaign }}{% endif %}"
             class="addlink">
            {% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
          </a>
        </li>
      {% endblock %}
    </ul>
  {% endif %}
{% endblock %}

然后将您的LocationAdmin类添加如下:

class LocationAdmin(EnhancedModelAdminMixin, admin.ModelAdmin):
    list_filter = 'campaign',
    list_display = 'location_name', 'campaign'

    change_list_template = 'your_app/admin/change_list.html'

    def changelist_view(self, request, extra_context=None):
        if 'campaign__id__exact' in getattr(request, request.method):
            selected_campaign = getattr(request, request.method)['campaign__id__exact']
            if not extra_context:
                extra_context = {'selected_campaign': selected_campaign}
            else:
                extra_context['selected_campaign'] = selected_campaign
        return super(LocationAdmin, self).changelist_view(request, extra_context)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'campaign':
            if 'selected_campaign' in getattr(request, request.method):
                kwargs['initial'] = getattr(request, request.method)['selected_campaign']
                return db_field.formfield(**kwargs)
        return super(LocationAdmin, self).formfield_for_foreignkey(
            db_field, request, **kwargs
        )

所以我们在这里做的是我们重写modeladmins changelist_view函数只是为了添加当前'selected_campaign'的附加上下文变量。

然后我们将它作为查询参数添加到添加新位置按钮。

最后,我们使用模型管理员formfield_for_foreignkey函数,根据用户点击添加新位置时收到的参数,动态定义广告系列字段的初始值。

干杯!如果您认为这有用,请不要忘记向上投票;)