天天看點

django admin自定義 自定義 Django admin

自定義 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="../../../" target="_blank" rel="external nofollow" >{% trans "Home" %}</a> &rsaquo;

    <a href="../../" target="_blank" rel="external nofollow" >{{ app_label|capfirst|

escape }}</a> &rsaquo;

    {% if has_change_permission %}<a

href="../" target="_blank" rel="external nofollow" >{{ 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="/" target="_blank" rel="external nofollow" >{% 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的首頁。