django admin自定义

本文介绍如何通过自定义Django的Admin界面来改善用户体验,包括调整UI界面、增加自定义视图、实现行级别权限控制等高级功能。

自定义 Django admin

核心观点

  1. UI是很重要的。
  2. 考虑初学者,DashBoard。
  3. 导航。
  4. 用户工作流。
  5. Django admin 缺少 WYSIWYG,文件管理,undo。

建议

  1. 了解用户的行业和工作流。
  2. 了解客户团队中的各个不同角色。
  3. 使用客户习语。
  4. 了解之前使用的工具,及其优缺点。

实现

ModelAdmin Media

class ArticleAdmin(admin.ModelAdmin):
    class Media:
        css = {
            "all": ("my_styles.css",)
        }
        js = ("my_code.js",)

优点:对于“一次性”项目简单。
缺点:只对Change Form有效。

Custom Templates

关键模板
  admin/base.html
  admin/index.html
  admin/change_form.html
  admin/change_list.html

  app_index.html
  delete_confirmation.html

  object_history.html
覆盖范围
  Across an entire project
  admin/change_form.html
  Across an application
  admin/<my_app>/change_form.html
  For an individual model
  admin/<my_app>/<my_model>/change_form.html
例如:
{% extends "admin/change_list.html" %}
{% block object-tools %}
    <h1 class="errornote">
        Look Here!
    </h1>
    {{ block.super }}
{% endblock %}
自定义模板的建议:
  Extend, don't override
  Use {{ block.super }} to extend blocks
  Extend a symlink of the admin templates in the event of recursion
  Extend the extrahead block in base.html for admin-wide media
已有项目:
http://code.google.com/p/sorl-curator/
http://code.google.com/p/django-grappelli/

ModelAdmin/ModelForm Hacking

注册ModelAdmin
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from demo_app.models import UserProfile
class UserProfileInline(admin.TabularInline):
    model = UserProfile
    fk_name = 'user'
    max_num = 1
class CustomUserAdmin(UserAdmin):
    inlines = [UserProfileInline, ]
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
行级别的权限
class ArticleAdmin(admin.ModelAdmin):
  def save_model(self, request, obj, form,
                                         change):
    obj.user = request.user
    obj.save()
  def queryset(self, request):
    qs = self.model._default_manager.filter(user=request.user)
    return qs
ModelForm
class AuthorForm(forms.ModelForm):
    exclude_states = ['AS', 'GU', 'MP', 'VI',]
    def __init__(self, *args, **kwargs):
        super(AuthorForm, self).__init__(*args,
                                      **kwargs)
        w = self.fields['state'].widget
        choices = []
        for key, value in w.choices:
            if key not in self.exclude_states:
                choices.append((key, value))
        w.choices = choices
class AuthorAdmin(admin.ModelAdmin):
    form = AuthorForm

Custom Views

Custom View URL
class PostAdmin(admin.ModelAdmin):
    def my_view(self, request):
        return admin_my_view(request, self)
    def get_urls(self):
        urls = super(PostAdmin, self).get_urls()
        my_urls = patterns('',
            (r'^my_view/$', self.my_view)
        )
        return my_urls + urls
Custom View
@permission_required('blog.add_post')
def admin_my_view(request, model_admin):
    opts = model_admin.model._meta
    admin_site = model_admin.admin_site
    has_perm = request.user.has_perm(opts.app_label /
                  + '.' + opts.get_change_permission())
    context = {'admin_site': admin_site.name,
        'title': "My Custom View",
        'opts': opts,
        'root_path': '/%s' % admin_site.root_path,
        'app_label': opts.app_label,
        'has_change_permission': has_perm}
    template = 'admin/demo_app/admin_my_view.html'
    return render_to_response(template, context,
              context_instance=RequestContext(request))
Custom View Template
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}
<div class="breadcrumbs">
    <a href="../../../">{% trans "Home" %}</a> &rsaquo;
    <a href="../../">{{ app_label|capfirst|
escape }}</a> &rsaquo;
    {% if has_change_permission %}<a
href="../">{{ opts.verbose_name_plural|
capfirst }}</a>{% else %}{{ opts.verbose_name_plural|
capfirst }}{% endif %} &rsaquo; My Custom View
</div>
{% endblock %}
{% block content %}
    <!-- do stuff here -->
{% endblock %}


Django的内置模板

base.html

<head>
    <title> {% block title %}{% endblock %} </title>
    {% block extrastyle %}{% endblock %}
    {% block extrahead %}{% endblock %}
</head>
{% load i18n %}
<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}">
<!-- Container -->
<div id="container">
    <div id="header">
        <div id="branding">
         {% block branding %}{% endblock %}
        </div>
        {% block nav-global %}{% endblock %}
    </div>
    <!-- END Header -->
    {% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} &rsaquo; {{ title }}{% endif %}</div>{% endblock %}

    <!-- Content -->
    <div id="content" class="{% block coltype %}colM{% endblock %}">
        {% block pretitle %}{% endblock %}
        {% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
        {% block content %}
             {% block object-tools %}{% endblock %}
        {{ content }}
        {% endblock %}
        {% block sidebar %}{% endblock %}
        <br class="clear" />
    </div>
    <!-- END Content -->

    {% block footer %}<div id="footer"></div>{% endblock %}
</div>
<!-- END Container -->

</body>

base_site.html

{% extends "admin/base.html" %}
{% load i18n %}

{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}

{% block branding %}
<h1 id="site-name">
    {% trans 'Customized Admin' %}
</h1>
{% endblock %}

{% block dashboard %}

{% endblock %}

{% block nav-global %}{% endblock %}

已有项目的调研

grappelli 用起来挺不错的。尤其是那个bookmarks很有用。至于navigation,感觉应该添加到每一个app的首页。
Django Admin 中创建自定义筛选器可以通过继承 `SimpleListFilter` 类来实现。此类提供了定义自定义筛选逻辑的接口,允许开发者为特定字段或逻辑添加筛选条件。 ### 自定义筛选器的基本结构 要创建一个自定义筛选器,需要定义一个继承自 `admin.SimpleListFilter` 的类,并实现以下方法: - `title`:指定筛选器在 Admin 页面上显示的标题。 - `parameter_name`:定义 URL 中使用的参数名称。 - `lookups`:定义筛选器的选项,返回一个包含元组的列表,每个元组包含一个值和对应的显示名称。 - `queryset`:根据选择的值返回过滤后的查询集。 ### 示例代码 以下是一个简单的示例,展示如何为模型中的某个字段创建自定义筛选器: ```python from django.contrib import admin class CustomFilter(admin.SimpleListFilter): title = '自定义筛选器' # 显示在 Admin 页面上的标题 parameter_name = 'custom_filter' # URL 中使用的参数名称 def lookups(self, request, model_admin): # 定义筛选器的选项 return ( ('option1', '选项1'), ('option2', '选项2'), ) def queryset(self, request, queryset): # 根据选择的值过滤查询集 if self.value() == 'option1': return queryset.filter(name__startswith='A') # 示例条件 elif self.value() == 'option2': return queryset.filter(name__startswith='B') # 示例条件 return queryset ``` ### 在 Admin 中使用自定义筛选器 定义好自定义筛选器后,需要将其应用到 Admin 类中。通过在 `list_filter` 中添加自定义筛选器,即可在 Admin 页面上使用。 ```python @admin.register(YourModel) class YourModelAdmin(admin.ModelAdmin): list_filter = [CustomFilter] # 添加自定义筛选器 ``` ### 多条件筛选 如果需要实现更复杂的筛选逻辑,可以在 `queryset` 方法中添加更多的条件判断。例如,可以根据多个字段进行筛选,或者结合其他模型的数据进行过滤。 ```python def queryset(self, request, queryset): if self.value() == 'option1': return queryset.filter(name__startswith='A').filter(age__gt=30) elif self.value() == 'option2': return queryset.filter(name__startswith='B').filter(age__lte=30) return queryset ``` ### 动态生成筛选选项 如果需要动态生成筛选选项,可以在 `lookups` 方法中根据模型数据生成选项。例如,从数据库中获取某个字段的所有唯一值。 ```python def lookups(self, request, model_admin): # 从数据库中获取唯一值 unique_values = YourModel.objects.values_list('your_field', flat=True).distinct() return [(value, value) for value in unique_values] ``` ### 结合用户权限 如果需要根据用户的权限动态调整筛选器的行为,可以在 `__init__` 方法中进行权限检查。 ```python def __init__(self, request, params, model, model_admin): super().__init__(request, params, model, model_admin) # 根据用户权限调整筛选器行为 if request.user.is_superuser: self.title = '管理员筛选器' ``` 通过这些方法,可以灵活地扩展 Django Admin 的筛选功能,满足不同的业务需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值