django-power-admin


Namedjango-power-admin JSON
Version 0.1.37 PyPI version JSON
download
home_page
SummaryDjango提供了快捷的生成后台管理站点的能力。本应用旨在增强Django Admin的能力,提供丰富的Admin、Widget、ListFilter、Form等等界面扩展类,同时也为常用的数据管理模型提供完整的管理功能。
upload_time2023-09-14 12:41:48
maintainerHe LianJia
docs_urlNone
authorHe LianJia
requires_python
licenseMIT
keywords django django admin django power admin django admin extensions
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-power-admin

Django提供了快捷的生成后台管理站点的能力。本应用旨在增强Django Admin的能力,提供丰富的Admin、Widget、ListFilter、Form等等界面扩展类,同时也为常用的数据管理模型提供完整的管理功能。

## 使用说明

1. 依赖`django-middleware-global-request`,请参考[django-middleware-global-request文档](https://pypi.org/project/django-middleware-global-request/)。
1. 依赖`django_static_fontawesome`,请参考[django_static_fontawesome文档](https://pypi.org/project/django-static-fontawesome/)。
1. 依赖`django_static_jquery_ui`,请参考[django_static_jquery_ui文档](https://pypi.org/project/django-static-jquery-ui/)。
1. 推荐使用`django-app-requires`解决包依赖问题,请参考[django-app-requires文档](https://pypi.org/project/django-app-requires/)。

## 功能扩展清单

### Admin后台管理界面整体控制

| 主要功能 |
| -------- |
| `@todo` 定制化的登录界面 |
| `@todo` 登录框增加图形验证码 |
| `@todo` 登录后增加短信验证 |
| `@todo` 顶部导航 |
| `@todo` 左侧导航 |
| `@todo` 首页控制面板 |
| `@todo` 应用模块级控制面板 |
| `@todo` 用户中心子站 |
| `@todo` 中国风的组织架构管理和用户管理 |

### PowerAdmin核心功能

| 类名 | 主要功能 |
| ---- | -------- |
| ChangelistToolbar机制 | 提供列表页顶部按钮自定义功能 |
| ChangelistObjectToolbar机制 | 提供列表页行按钮自定义功能 |
| Extra View机制 | 提供添加额外视图函数的功能 |
| View Hook机制 | 提供pre_xxx_view,post_xxx_view的Hook机制,<br />方便用户在进入视图前执行准备或清除工作 |
| Extra Context机制 | 为视图渲染注入额外的模板context机制。<br />`ChangelistToolbar机制`就是通过本机制注入额外的按钮列表数据的。 |
| Read & Change机制 | 设置只读、编辑两个不同的入口。这样现符合用户的操作习惯。 |
| Simple Export机制 | 数据导出机制,<br />默认即可导出所有表字段,<br />同时支持EXCEL模板配置、表头控制、字段配置等等。 |
| [排序记录上下移动机制](#django_power_admin.admin.PowerAdmin排序记录上下移动机制) | 每行记录上有上移&下移按钮,<br />通过点击上下移动按钮调整记录的排序。|
| [ListFilter Media机制](#django_power_admin.widgets.TextInputFieldFilter实现原理) | 允许自定义的ListFilter类,<br />通过添加`class Media:`来引入额外的js/css文件。 |

### Admin辅助函数
| 函数名 | 主要功能 |
| ---- | -------- |
| add_extra_css | 为当前页添加额外的css代码段 |
| add_extra_js | 为当前页添加额外的js代码段 |


### Widget扩展类

| 类名 | 主要功能 |
| ---- | -------- |
| [Select2](#django_power_admin.widgets.Select2) | 将标准select下拉框转为select2样式下拉框 |
| SelectMultiple2 | 将标准select复选框转为select2样式下拉式复选框 |
| [ConfigTable](#django_power_admin.widgets.ConfigTable) | 健值对配置项编辑控件<br />数据json序列化后保存在TextField中 |
| PopupConfigTable | 弹出式健值对配置项编辑控件<br />数据json序列化后保存在TextField中 |
| [AllUsersSelect](#django_power_admin.widgets.AllUsersSelect) | 用户选择控件,使用Select2实现<br />提供用户信息模糊搜索功能<br />不需要用户模块管理权限 |
| `@todo` PasswordResetableWidget | 密码重置字段(只重置,不显示)|

### Field扩展类

| 类名 | 主要功能 |
| ---- | -------- |
| MPTTModelChoiceField | MPTT数据模型中的Parent字段关联的表单字段,<br />使用Select2样式控件。<br />建议在MPTTAdminForm中使用 |
| ModelChoiceFieldWithLabelProperty | 标准ModelChoiceField的扩展,<br />支持使用自定义的标签函数 |

### Form扩展类

### ListFilter扩展类

| 类名 | 主要功能 |
| --- | ----- |
| [TextInputFieldFilter](#django_power_admin.filters.TextInputFieldFilter)  | 使用文本框的过滤条件。 |
| [DateRangeFilter](#django_power_admin.filters.DateRangeFilter)  | 日期区间过滤条件。 |


## 使用方法说明

### django_power_admin的引入

*pro/settings.py*

```
INSTALLED_APPS = [
    ...
    'django_middleware_global_request',
    'django_static_fontawesome',
    'django_static_jquery_ui',
    'django_simple_tags',
    'django_power_admin',
    ...
]

MIDDLEWARE = [
    ...
    'django_middleware_global_request.middleware.GlobalRequestMiddleware',
    ...
]

```

### <a name="django_power_admin.admin.PowerAdmin排序记录上下移动机制"></a>django_power_admin.admin.PowerAdmin排序记录上下移动机制

#### django_power_admin.admin.PowerAdmin排序记录上下移动机制效果图

![django_power_admin.admin.PowerAdmin排序支持效果预览图](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/admin/django_power_admin_admin_sorting_preview.png)


#### django_power_admin.admin.PowerAdmin排序记录上下移动机制使用方法

*models.py*

```
class SortableAdminExmapleModel(models.Model):
    title = models.CharField(max_length=64, verbose_name="Title")
    display_order = models.IntegerField(null=True, blank=True, verbose_name="Display Order")

    class Meta:
        verbose_name = "排序演示"
        verbose_name_plural = "排序演示"
    
    def __str__(self):
        return str(self.pk)

```

*admin.py*

```
from django.contrib import admin

from django_power_admin.admin import PowerAdmin

from .models import SortableAdminExmapleModel


class SortableAdminExmapleModelAdmin(PowerAdmin):
    list_display = ["title"]
    ordering = ["display_order"]
    changelist_object_toolbar_buttons = [
        "django_power_admin_move_up",
        "django_power_admin_move_down",
        "read_button",
        "change_button",
        "delete_button",
    ]

admin.site.register(SortableAdminExmapleModel, SortableAdminExmapleModelAdmin)

```

### <a name="django_power_admin.widgets.Select2"></a>django_power_admin.widgets.Select2

#### django_power_admin.widgets.Select2效果预览图

![django_power_admin.widgets.Select2效果预览图](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/widgets/Select2/django_power_admin_widgets_select2_preview.png)

#### django_power_admin.widgets.Select2使用方法

*models.py*

```
from django.db import models

class Select2ExampleCategory(models.Model):
    name = models.CharField(max_length=64, verbose_name="Name")

    class Meta:
        verbose_name = "Category"
        verbose_name_plural = "Categories"
    
    def __str__(self):
        return self.name

class Select2ExampleModel(models.Model):
    title = models.CharField(max_length=64, verbose_name="Title")
    category = models.ForeignKey(Select2ExampleCategory, on_delete=models.CASCADE, verbose_name="Category")

    class Meta:
        verbose_name = "可搜索下拉框演示"
        verbose_name_plural = "可搜索下拉框演示"

    def __str__(self):
        return self.title

```

*admin.py*

```
from django import forms
from django.contrib import admin

from django_power_admin.widgets import Select2

from .models import Select2ExampleCategory
from .models import Select2ExampleModel


class Select2ExampleCategoryAdmin(admin.ModelAdmin):
    list_display = ["name"]

class Select2ExampleModelForm(forms.ModelForm):
    class Meta:
        widgets = {
            "category": Select2(),
        }

class Select2ExampleModelAdmin(admin.ModelAdmin):
    form = Select2ExampleModelForm
    list_display = ["title"]

admin.site.register(Select2ExampleCategory, Select2ExampleCategoryAdmin)
admin.site.register(Select2ExampleModel, Select2ExampleModelAdmin)

```


### <a name="django_power_admin.widgets.ConfigTable"></a>django_power_admin.widgets.ConfigTable

#### django_power_admin.widgets.ConfigTable效果预览图

![django_power_admin.widgets.ConfigTable效果预览图](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/widgets/ConfigTable/django_power_admin_widgets_config_table_preview.png)

#### django_power_admin.widgets.ConfigTable使用方法

*models.py*

```
from django.db import models

class ConfigTableExampleModel(models.Model):
    config = models.TextField(null=True, blank=True, verbose_name="配置")
    
    class Meta:
        verbose_name = "配置表控件演示"
        verbose_name_plural = "配置表控件演示"

    def __str__(self):
        return str(self.pk)
```

*admin.py*

```
from django import forms
from django.contrib import admin

from django_power_admin.widgets import ConfigTable

class ConfigTableExampleModelForm(forms.ModelForm):
    class Meta:
        widgets = {
            "config": ConfigTable(),
        }

class ConfigTableExampleModelAdmin(admin.ModelAdmin):
    form = ConfigTableExampleModelForm

admin.site.register(ConfigTableExampleModel, ConfigTableExampleModelAdmin)
```

### <a name="django_power_admin.widgets.AllUsersSelect"></a>django_power_admin.widgets.AllUsersSelect

#### django_power_admin.widgets.AllUsersSelect预览效果

![django_power_admin.widgets.AllUsersSelect效果预览图](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/widgets/AllUsersSelect/AllUsersSelect.png)


#### django_power_admin.widgets.AllUsersSelect使用方法

*models.py*

```
from django.db import models

class Project(models.Model):
    
    owner = models.ForeignKey(global_settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name="+", verbose_name=_("Owner"))

    class Meta:
        verbose_name = "Project"
        verbose_name_plural = "Projects"

    def __str__(self):
        return str(self.pk)
```

*admin.py*

```
from django import forms
from django.contrib import admin
from django_power_admin.widgets import AllUsersSelect
from .models import Project

class ProjectForm(forms.ModelForm):
    class Meta:
        widgets = {
            "owner": AllUsersSelect(),
        }

class ProjectAdmin(admin.ModelAdmin):
    form = ProjectForm

admin.site.register(Project, ProjectAdmin)
```

### <a name="django_power_admin.filters.TextInputFieldFilter"></a>django_power_admin.widgets.TextInputFieldFilter

#### django_power_admin.filters.TextInputFieldFilter预览效果

![django_power_admin.filters.TextInputFieldFilter预览效果](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/filters/TextInputFieldFilter/TextInputFieldFilter.png)


#### django_power_admin.filters.TextInputFieldFilter使用方法

```
from django.contrib import admin
from django_power_admin.filters import TextInputFieldFilter

class ExampleAdmin(admin.ModelAdmin):
    list_filter = [
        ("title", TextInputFieldFilter),
        "description",
        "enable",
    ]
    list_display = ["title", "description", "enable"]
```

#### <a name="django_power_admin.filters.TextInputFieldFilter实现原理"></a>django_power_admin.filters.TextInputFieldFilter实现原理

使用了django_power_admin引入的ListFilter Media机制,
通过在类内部定义`class Media`,
导入ListFilter需要使用到的js/css文件,
导入的js文件,可以按django标准media文件引入机制进行自动化的去重和依赖排序。


```
from django.contrib.admin import FieldListFilter

class TextInputFieldFilter(FieldListFilter):
    template = 'django_power_admin/filters/TextInputFieldFilter.html'

    ...

    class Media:
        css = {
            "all": [
                "django_power_admin/filters/TextInputFieldFilter/css/TextInputFieldFilter.css",
            ]
        }
        js = [
            "django_power_admin/assets/js/parseParam.js",
            "admin/js/vendor/jquery/jquery.js",
            "django_power_admin/filters/TextInputFieldFilter/js/TextInputFieldFilter.js",
            "admin/js/jquery.init.js",
        ]

```

### <a name="django_power_admin.filters.DateRangeFilter"></a>django_power_admin.filters.DateRangeFilter

#### django_power_admin.filters.DateRangeFilter效果预览

![django_power_admin.filters.DateRangeFilter](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/filters/DateRangeFilter/DateRangeFilter.png)


#### django_power_admin.filters.DateRangeFilter使用方式

```
from django.contrib import admin
from django_power_admin.filters import DateRangeFilter

class ExampleAdmin(admin.ModelAdmin):
    list_filter = [
        "username",
        ("date_join", DateRangeFilter),
        "is_active",
    ]
    list_display = ["username", "date_join", "is_active"]
```

### Admin样式类

- inline-narror-input

    TabularInline字符串输入框改为小框。

    *使用范围:*

    - 可加在TabularInline类的claases属性中。

- related-actions-hidden

    隐藏外键的增改删按钮。

    *使用范围:*

    - 可加在fieldsets的classes属性中。
    - 可以加在TabularInline类的claases属性中。

- inline-original-hidden

    隐藏TabularInline及StackInline中的orininal显示。

    *使用范围:*

    - 可加在TabularInline类的claases属性中。
    - 可加在StackInline类的claases属性中。

- form-row-c2

    FormChange表单两例显示,同时控制textarea的宽度。

    *使用范围:*

    - 可加在fieldsets的classes属性中。

### Admin全局控制

- DJANGO_ADMIN_USE_FIXED_WIDTH_LAYOUT

    当DJANGO_ADMIN_USE_FIXED_WIDTH_LAYOUT=True,Admin管理后台设置为固定宽度,且居中显示。可通过以下设置控制宽度及背景色。

    *关联设置项:*

    - DJANGO_ADMIN_USE_FIXED_WIDTH_LAYOUT = False
    - DJANGO_ADMIN_WIDTH = 1280px
    - DJANGO_ADMIN_BACKGROUND_COLOR = "#f5f6f8"
    - DJANGO_ADMIN_FOOTER_COLOR = "#c5cbd2"


## 版本记录

### v0.1.7

- 项目启动。
- 框架搭建。
- PowerAdmin类基本完成。

### v0.1.10

- get_extra_views更名为get_extra_view_urls,避免与其它方法名冲突。
- view_action更名为read_xxx。xxx_action更名为xxx_button。
- 在list_display中追加change_list_object_toolbar字段。

### v0.1.12

- 增加has_change_permission_real, has_delete_permission_real方法,解决read/change机制导致的原始权限判断丢失的情况。
- 增加get_messages方法, 用于获取站点当前的messages队列。
- 增加get_power_admin_class,用于统一扩展所有PowerAdmin的子类。

### v0.1.18

- 修正get_changelist_object_row_classes_javascript方法在遇到其它错误时导致的异常行为。
- ChangelistObjectToolbarButton可以直接引用extra view(需要为extra view添加按钮额外属性,如:short_description、icon、classes等)。
- change_list_xxx更名为changelist_xxx(注意:可能引起新旧版本的不兼容,特别是子类配置的change_list_toolbar_buttons属性需要改名为changelist_toolbar_buttons)。
- 引入ChangelistToolbar机制,用于添加额外的列表页顶部按钮。

### v0.1.20

- 添加简易数据分享机制的支持(simple share model)。
- 添加数据导出功能。

### v0.1.21

- 添加适用于TextField使用的“键值对”控件。
- PowerAdmin中方法名加上django_power_admin_前缀,避免与其它扩展类冲突。

### v0.1.23

- 修正Select2、SelectMultiple2、ConfigTable在inline表单中的使用问题。
- 新增django_power_admin.widgets.AllUsersSelect。

### v0.1.24

- 新增django_power_admin.filters.TextInputFieldFilter。
- 新增list_filter类通过定义内部的`Media:`引入额外的js/css文件的机制。

### v0.1.25

- 新增django_power_admin.filters.DateRangeFilter。

### v0.1.27

- 修正ChangelistObjectToolbar按钮换行的问题。

### v0.1.29

- 兼容django 4.x。
- 兼容python 2.7。
- 修正排序Admin未设置ordering时的异常。

### v0.1.30

- 修正get_ordering强制添加display_order字段导致的问题。

### v0.1.31

- 修正ChangelistObjectToolBarButton的默认target=self问题,修正后的默认target=_self。
- 使用zenutils依赖包以简化不必要的依赖关系。

### v0.1.35

- 修正DateRangeFilter结束日期框搜索条件名称错误的问题。

### v0.1.36

- 增加站点固定宽度居中。
- 增加Admin样式类:form-row-c2、inline-original-hidden、related-actions-hidden、inline-narror-input。
- 增加PopupConfigTable控件。

### v0.1.37

- 文档更新。

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "django-power-admin",
    "maintainer": "He LianJia",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "helianjia@zencore.cn",
    "keywords": "django,django admin,django power admin,django admin extensions",
    "author": "He LianJia",
    "author_email": "helianjia@zencore.cn",
    "download_url": "https://files.pythonhosted.org/packages/ca/5b/18440bf9b0a538d109be7e4db1188e999f5b3db4668d0822a1f2eba99073/django-power-admin-0.1.37.tar.gz",
    "platform": null,
    "description": "# django-power-admin\n\nDjango\u63d0\u4f9b\u4e86\u5feb\u6377\u7684\u751f\u6210\u540e\u53f0\u7ba1\u7406\u7ad9\u70b9\u7684\u80fd\u529b\u3002\u672c\u5e94\u7528\u65e8\u5728\u589e\u5f3aDjango Admin\u7684\u80fd\u529b\uff0c\u63d0\u4f9b\u4e30\u5bcc\u7684Admin\u3001Widget\u3001ListFilter\u3001Form\u7b49\u7b49\u754c\u9762\u6269\u5c55\u7c7b\uff0c\u540c\u65f6\u4e5f\u4e3a\u5e38\u7528\u7684\u6570\u636e\u7ba1\u7406\u6a21\u578b\u63d0\u4f9b\u5b8c\u6574\u7684\u7ba1\u7406\u529f\u80fd\u3002\n\n## \u4f7f\u7528\u8bf4\u660e\n\n1. \u4f9d\u8d56`django-middleware-global-request`\uff0c\u8bf7\u53c2\u8003[django-middleware-global-request\u6587\u6863](https://pypi.org/project/django-middleware-global-request/)\u3002\n1. \u4f9d\u8d56`django_static_fontawesome`\uff0c\u8bf7\u53c2\u8003[django_static_fontawesome\u6587\u6863](https://pypi.org/project/django-static-fontawesome/)\u3002\n1. \u4f9d\u8d56`django_static_jquery_ui`\uff0c\u8bf7\u53c2\u8003[django_static_jquery_ui\u6587\u6863](https://pypi.org/project/django-static-jquery-ui/)\u3002\n1. \u63a8\u8350\u4f7f\u7528`django-app-requires`\u89e3\u51b3\u5305\u4f9d\u8d56\u95ee\u9898\uff0c\u8bf7\u53c2\u8003[django-app-requires\u6587\u6863](https://pypi.org/project/django-app-requires/)\u3002\n\n## \u529f\u80fd\u6269\u5c55\u6e05\u5355\n\n### Admin\u540e\u53f0\u7ba1\u7406\u754c\u9762\u6574\u4f53\u63a7\u5236\n\n| \u4e3b\u8981\u529f\u80fd |\n| -------- |\n| `@todo` \u5b9a\u5236\u5316\u7684\u767b\u5f55\u754c\u9762 |\n| `@todo` \u767b\u5f55\u6846\u589e\u52a0\u56fe\u5f62\u9a8c\u8bc1\u7801 |\n| `@todo` \u767b\u5f55\u540e\u589e\u52a0\u77ed\u4fe1\u9a8c\u8bc1 |\n| `@todo` \u9876\u90e8\u5bfc\u822a |\n| `@todo` \u5de6\u4fa7\u5bfc\u822a |\n| `@todo` \u9996\u9875\u63a7\u5236\u9762\u677f |\n| `@todo` \u5e94\u7528\u6a21\u5757\u7ea7\u63a7\u5236\u9762\u677f |\n| `@todo` \u7528\u6237\u4e2d\u5fc3\u5b50\u7ad9 |\n| `@todo` \u4e2d\u56fd\u98ce\u7684\u7ec4\u7ec7\u67b6\u6784\u7ba1\u7406\u548c\u7528\u6237\u7ba1\u7406 |\n\n### PowerAdmin\u6838\u5fc3\u529f\u80fd\n\n| \u7c7b\u540d | \u4e3b\u8981\u529f\u80fd |\n| ---- | -------- |\n| ChangelistToolbar\u673a\u5236 | \u63d0\u4f9b\u5217\u8868\u9875\u9876\u90e8\u6309\u94ae\u81ea\u5b9a\u4e49\u529f\u80fd |\n| ChangelistObjectToolbar\u673a\u5236 | \u63d0\u4f9b\u5217\u8868\u9875\u884c\u6309\u94ae\u81ea\u5b9a\u4e49\u529f\u80fd |\n| Extra View\u673a\u5236 | \u63d0\u4f9b\u6dfb\u52a0\u989d\u5916\u89c6\u56fe\u51fd\u6570\u7684\u529f\u80fd |\n| View Hook\u673a\u5236 | \u63d0\u4f9bpre_xxx_view\uff0cpost_xxx_view\u7684Hook\u673a\u5236\uff0c<br />\u65b9\u4fbf\u7528\u6237\u5728\u8fdb\u5165\u89c6\u56fe\u524d\u6267\u884c\u51c6\u5907\u6216\u6e05\u9664\u5de5\u4f5c |\n| Extra Context\u673a\u5236 | \u4e3a\u89c6\u56fe\u6e32\u67d3\u6ce8\u5165\u989d\u5916\u7684\u6a21\u677fcontext\u673a\u5236\u3002<br />`ChangelistToolbar\u673a\u5236`\u5c31\u662f\u901a\u8fc7\u672c\u673a\u5236\u6ce8\u5165\u989d\u5916\u7684\u6309\u94ae\u5217\u8868\u6570\u636e\u7684\u3002 |\n| Read & Change\u673a\u5236 | \u8bbe\u7f6e\u53ea\u8bfb\u3001\u7f16\u8f91\u4e24\u4e2a\u4e0d\u540c\u7684\u5165\u53e3\u3002\u8fd9\u6837\u73b0\u7b26\u5408\u7528\u6237\u7684\u64cd\u4f5c\u4e60\u60ef\u3002 |\n| Simple Export\u673a\u5236 | \u6570\u636e\u5bfc\u51fa\u673a\u5236\uff0c<br />\u9ed8\u8ba4\u5373\u53ef\u5bfc\u51fa\u6240\u6709\u8868\u5b57\u6bb5\uff0c<br />\u540c\u65f6\u652f\u6301EXCEL\u6a21\u677f\u914d\u7f6e\u3001\u8868\u5934\u63a7\u5236\u3001\u5b57\u6bb5\u914d\u7f6e\u7b49\u7b49\u3002 |\n| [\u6392\u5e8f\u8bb0\u5f55\u4e0a\u4e0b\u79fb\u52a8\u673a\u5236](#django_power_admin.admin.PowerAdmin\u6392\u5e8f\u8bb0\u5f55\u4e0a\u4e0b\u79fb\u52a8\u673a\u5236) | \u6bcf\u884c\u8bb0\u5f55\u4e0a\u6709\u4e0a\u79fb&\u4e0b\u79fb\u6309\u94ae\uff0c<br />\u901a\u8fc7\u70b9\u51fb\u4e0a\u4e0b\u79fb\u52a8\u6309\u94ae\u8c03\u6574\u8bb0\u5f55\u7684\u6392\u5e8f\u3002|\n| [ListFilter Media\u673a\u5236](#django_power_admin.widgets.TextInputFieldFilter\u5b9e\u73b0\u539f\u7406) | \u5141\u8bb8\u81ea\u5b9a\u4e49\u7684ListFilter\u7c7b\uff0c<br />\u901a\u8fc7\u6dfb\u52a0`class Media:`\u6765\u5f15\u5165\u989d\u5916\u7684js/css\u6587\u4ef6\u3002 |\n\n### Admin\u8f85\u52a9\u51fd\u6570\n| \u51fd\u6570\u540d | \u4e3b\u8981\u529f\u80fd |\n| ---- | -------- |\n| add_extra_css | \u4e3a\u5f53\u524d\u9875\u6dfb\u52a0\u989d\u5916\u7684css\u4ee3\u7801\u6bb5 |\n| add_extra_js | \u4e3a\u5f53\u524d\u9875\u6dfb\u52a0\u989d\u5916\u7684js\u4ee3\u7801\u6bb5 |\n\n\n### Widget\u6269\u5c55\u7c7b\n\n| \u7c7b\u540d | \u4e3b\u8981\u529f\u80fd |\n| ---- | -------- |\n| [Select2](#django_power_admin.widgets.Select2) | \u5c06\u6807\u51c6select\u4e0b\u62c9\u6846\u8f6c\u4e3aselect2\u6837\u5f0f\u4e0b\u62c9\u6846 |\n| SelectMultiple2 | \u5c06\u6807\u51c6select\u590d\u9009\u6846\u8f6c\u4e3aselect2\u6837\u5f0f\u4e0b\u62c9\u5f0f\u590d\u9009\u6846 |\n| [ConfigTable](#django_power_admin.widgets.ConfigTable) | \u5065\u503c\u5bf9\u914d\u7f6e\u9879\u7f16\u8f91\u63a7\u4ef6<br />\u6570\u636ejson\u5e8f\u5217\u5316\u540e\u4fdd\u5b58\u5728TextField\u4e2d |\n| PopupConfigTable | \u5f39\u51fa\u5f0f\u5065\u503c\u5bf9\u914d\u7f6e\u9879\u7f16\u8f91\u63a7\u4ef6<br />\u6570\u636ejson\u5e8f\u5217\u5316\u540e\u4fdd\u5b58\u5728TextField\u4e2d |\n| [AllUsersSelect](#django_power_admin.widgets.AllUsersSelect) | \u7528\u6237\u9009\u62e9\u63a7\u4ef6\uff0c\u4f7f\u7528Select2\u5b9e\u73b0<br />\u63d0\u4f9b\u7528\u6237\u4fe1\u606f\u6a21\u7cca\u641c\u7d22\u529f\u80fd<br />\u4e0d\u9700\u8981\u7528\u6237\u6a21\u5757\u7ba1\u7406\u6743\u9650 |\n| `@todo` PasswordResetableWidget | \u5bc6\u7801\u91cd\u7f6e\u5b57\u6bb5\uff08\u53ea\u91cd\u7f6e\uff0c\u4e0d\u663e\u793a\uff09|\n\n### Field\u6269\u5c55\u7c7b\n\n| \u7c7b\u540d | \u4e3b\u8981\u529f\u80fd |\n| ---- | -------- |\n| MPTTModelChoiceField | MPTT\u6570\u636e\u6a21\u578b\u4e2d\u7684Parent\u5b57\u6bb5\u5173\u8054\u7684\u8868\u5355\u5b57\u6bb5\uff0c<br />\u4f7f\u7528Select2\u6837\u5f0f\u63a7\u4ef6\u3002<br />\u5efa\u8bae\u5728MPTTAdminForm\u4e2d\u4f7f\u7528 |\n| ModelChoiceFieldWithLabelProperty | \u6807\u51c6ModelChoiceField\u7684\u6269\u5c55\uff0c<br />\u652f\u6301\u4f7f\u7528\u81ea\u5b9a\u4e49\u7684\u6807\u7b7e\u51fd\u6570 |\n\n### Form\u6269\u5c55\u7c7b\n\n### ListFilter\u6269\u5c55\u7c7b\n\n| \u7c7b\u540d | \u4e3b\u8981\u529f\u80fd |\n| --- | ----- |\n| [TextInputFieldFilter](#django_power_admin.filters.TextInputFieldFilter)  | \u4f7f\u7528\u6587\u672c\u6846\u7684\u8fc7\u6ee4\u6761\u4ef6\u3002 |\n| [DateRangeFilter](#django_power_admin.filters.DateRangeFilter)  | \u65e5\u671f\u533a\u95f4\u8fc7\u6ee4\u6761\u4ef6\u3002 |\n\n\n## \u4f7f\u7528\u65b9\u6cd5\u8bf4\u660e\n\n### django_power_admin\u7684\u5f15\u5165\n\n*pro/settings.py*\n\n```\nINSTALLED_APPS = [\n    ...\n    'django_middleware_global_request',\n    'django_static_fontawesome',\n    'django_static_jquery_ui',\n    'django_simple_tags',\n    'django_power_admin',\n    ...\n]\n\nMIDDLEWARE = [\n    ...\n    'django_middleware_global_request.middleware.GlobalRequestMiddleware',\n    ...\n]\n\n```\n\n### <a name=\"django_power_admin.admin.PowerAdmin\u6392\u5e8f\u8bb0\u5f55\u4e0a\u4e0b\u79fb\u52a8\u673a\u5236\"></a>django_power_admin.admin.PowerAdmin\u6392\u5e8f\u8bb0\u5f55\u4e0a\u4e0b\u79fb\u52a8\u673a\u5236\n\n#### django_power_admin.admin.PowerAdmin\u6392\u5e8f\u8bb0\u5f55\u4e0a\u4e0b\u79fb\u52a8\u673a\u5236\u6548\u679c\u56fe\n\n![django_power_admin.admin.PowerAdmin\u6392\u5e8f\u652f\u6301\u6548\u679c\u9884\u89c8\u56fe](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/admin/django_power_admin_admin_sorting_preview.png)\n\n\n#### django_power_admin.admin.PowerAdmin\u6392\u5e8f\u8bb0\u5f55\u4e0a\u4e0b\u79fb\u52a8\u673a\u5236\u4f7f\u7528\u65b9\u6cd5\n\n*models.py*\n\n```\nclass SortableAdminExmapleModel(models.Model):\n    title = models.CharField(max_length=64, verbose_name=\"Title\")\n    display_order = models.IntegerField(null=True, blank=True, verbose_name=\"Display Order\")\n\n    class Meta:\n        verbose_name = \"\u6392\u5e8f\u6f14\u793a\"\n        verbose_name_plural = \"\u6392\u5e8f\u6f14\u793a\"\n    \n    def __str__(self):\n        return str(self.pk)\n\n```\n\n*admin.py*\n\n```\nfrom django.contrib import admin\n\nfrom django_power_admin.admin import PowerAdmin\n\nfrom .models import SortableAdminExmapleModel\n\n\nclass SortableAdminExmapleModelAdmin(PowerAdmin):\n    list_display = [\"title\"]\n    ordering = [\"display_order\"]\n    changelist_object_toolbar_buttons = [\n        \"django_power_admin_move_up\",\n        \"django_power_admin_move_down\",\n        \"read_button\",\n        \"change_button\",\n        \"delete_button\",\n    ]\n\nadmin.site.register(SortableAdminExmapleModel, SortableAdminExmapleModelAdmin)\n\n```\n\n### <a name=\"django_power_admin.widgets.Select2\"></a>django_power_admin.widgets.Select2\n\n#### django_power_admin.widgets.Select2\u6548\u679c\u9884\u89c8\u56fe\n\n![django_power_admin.widgets.Select2\u6548\u679c\u9884\u89c8\u56fe](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/widgets/Select2/django_power_admin_widgets_select2_preview.png)\n\n#### django_power_admin.widgets.Select2\u4f7f\u7528\u65b9\u6cd5\n\n*models.py*\n\n```\nfrom django.db import models\n\nclass Select2ExampleCategory(models.Model):\n    name = models.CharField(max_length=64, verbose_name=\"Name\")\n\n    class Meta:\n        verbose_name = \"Category\"\n        verbose_name_plural = \"Categories\"\n    \n    def __str__(self):\n        return self.name\n\nclass Select2ExampleModel(models.Model):\n    title = models.CharField(max_length=64, verbose_name=\"Title\")\n    category = models.ForeignKey(Select2ExampleCategory, on_delete=models.CASCADE, verbose_name=\"Category\")\n\n    class Meta:\n        verbose_name = \"\u53ef\u641c\u7d22\u4e0b\u62c9\u6846\u6f14\u793a\"\n        verbose_name_plural = \"\u53ef\u641c\u7d22\u4e0b\u62c9\u6846\u6f14\u793a\"\n\n    def __str__(self):\n        return self.title\n\n```\n\n*admin.py*\n\n```\nfrom django import forms\nfrom django.contrib import admin\n\nfrom django_power_admin.widgets import Select2\n\nfrom .models import Select2ExampleCategory\nfrom .models import Select2ExampleModel\n\n\nclass Select2ExampleCategoryAdmin(admin.ModelAdmin):\n    list_display = [\"name\"]\n\nclass Select2ExampleModelForm(forms.ModelForm):\n    class Meta:\n        widgets = {\n            \"category\": Select2(),\n        }\n\nclass Select2ExampleModelAdmin(admin.ModelAdmin):\n    form = Select2ExampleModelForm\n    list_display = [\"title\"]\n\nadmin.site.register(Select2ExampleCategory, Select2ExampleCategoryAdmin)\nadmin.site.register(Select2ExampleModel, Select2ExampleModelAdmin)\n\n```\n\n\n### <a name=\"django_power_admin.widgets.ConfigTable\"></a>django_power_admin.widgets.ConfigTable\n\n#### django_power_admin.widgets.ConfigTable\u6548\u679c\u9884\u89c8\u56fe\n\n![django_power_admin.widgets.ConfigTable\u6548\u679c\u9884\u89c8\u56fe](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/widgets/ConfigTable/django_power_admin_widgets_config_table_preview.png)\n\n#### django_power_admin.widgets.ConfigTable\u4f7f\u7528\u65b9\u6cd5\n\n*models.py*\n\n```\nfrom django.db import models\n\nclass ConfigTableExampleModel(models.Model):\n    config = models.TextField(null=True, blank=True, verbose_name=\"\u914d\u7f6e\")\n    \n    class Meta:\n        verbose_name = \"\u914d\u7f6e\u8868\u63a7\u4ef6\u6f14\u793a\"\n        verbose_name_plural = \"\u914d\u7f6e\u8868\u63a7\u4ef6\u6f14\u793a\"\n\n    def __str__(self):\n        return str(self.pk)\n```\n\n*admin.py*\n\n```\nfrom django import forms\nfrom django.contrib import admin\n\nfrom django_power_admin.widgets import ConfigTable\n\nclass ConfigTableExampleModelForm(forms.ModelForm):\n    class Meta:\n        widgets = {\n            \"config\": ConfigTable(),\n        }\n\nclass ConfigTableExampleModelAdmin(admin.ModelAdmin):\n    form = ConfigTableExampleModelForm\n\nadmin.site.register(ConfigTableExampleModel, ConfigTableExampleModelAdmin)\n```\n\n### <a name=\"django_power_admin.widgets.AllUsersSelect\"></a>django_power_admin.widgets.AllUsersSelect\n\n#### django_power_admin.widgets.AllUsersSelect\u9884\u89c8\u6548\u679c\n\n![django_power_admin.widgets.AllUsersSelect\u6548\u679c\u9884\u89c8\u56fe](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/widgets/AllUsersSelect/AllUsersSelect.png)\n\n\n#### django_power_admin.widgets.AllUsersSelect\u4f7f\u7528\u65b9\u6cd5\n\n*models.py*\n\n```\nfrom django.db import models\n\nclass Project(models.Model):\n    \n    owner = models.ForeignKey(global_settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name=\"+\", verbose_name=_(\"Owner\"))\n\n    class Meta:\n        verbose_name = \"Project\"\n        verbose_name_plural = \"Projects\"\n\n    def __str__(self):\n        return str(self.pk)\n```\n\n*admin.py*\n\n```\nfrom django import forms\nfrom django.contrib import admin\nfrom django_power_admin.widgets import AllUsersSelect\nfrom .models import Project\n\nclass ProjectForm(forms.ModelForm):\n    class Meta:\n        widgets = {\n            \"owner\": AllUsersSelect(),\n        }\n\nclass ProjectAdmin(admin.ModelAdmin):\n    form = ProjectForm\n\nadmin.site.register(Project, ProjectAdmin)\n```\n\n### <a name=\"django_power_admin.filters.TextInputFieldFilter\"></a>django_power_admin.widgets.TextInputFieldFilter\n\n#### django_power_admin.filters.TextInputFieldFilter\u9884\u89c8\u6548\u679c\n\n![django_power_admin.filters.TextInputFieldFilter\u9884\u89c8\u6548\u679c](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/filters/TextInputFieldFilter/TextInputFieldFilter.png)\n\n\n#### django_power_admin.filters.TextInputFieldFilter\u4f7f\u7528\u65b9\u6cd5\n\n```\nfrom django.contrib import admin\nfrom django_power_admin.filters import TextInputFieldFilter\n\nclass ExampleAdmin(admin.ModelAdmin):\n    list_filter = [\n        (\"title\", TextInputFieldFilter),\n        \"description\",\n        \"enable\",\n    ]\n    list_display = [\"title\", \"description\", \"enable\"]\n```\n\n#### <a name=\"django_power_admin.filters.TextInputFieldFilter\u5b9e\u73b0\u539f\u7406\"></a>django_power_admin.filters.TextInputFieldFilter\u5b9e\u73b0\u539f\u7406\n\n\u4f7f\u7528\u4e86django_power_admin\u5f15\u5165\u7684ListFilter Media\u673a\u5236\uff0c\n\u901a\u8fc7\u5728\u7c7b\u5185\u90e8\u5b9a\u4e49`class Media`\uff0c\n\u5bfc\u5165ListFilter\u9700\u8981\u4f7f\u7528\u5230\u7684js/css\u6587\u4ef6\uff0c\n\u5bfc\u5165\u7684js\u6587\u4ef6\uff0c\u53ef\u4ee5\u6309django\u6807\u51c6media\u6587\u4ef6\u5f15\u5165\u673a\u5236\u8fdb\u884c\u81ea\u52a8\u5316\u7684\u53bb\u91cd\u548c\u4f9d\u8d56\u6392\u5e8f\u3002\n\n\n```\nfrom django.contrib.admin import FieldListFilter\n\nclass TextInputFieldFilter(FieldListFilter):\n    template = 'django_power_admin/filters/TextInputFieldFilter.html'\n\n    ...\n\n    class Media:\n        css = {\n            \"all\": [\n                \"django_power_admin/filters/TextInputFieldFilter/css/TextInputFieldFilter.css\",\n            ]\n        }\n        js = [\n            \"django_power_admin/assets/js/parseParam.js\",\n            \"admin/js/vendor/jquery/jquery.js\",\n            \"django_power_admin/filters/TextInputFieldFilter/js/TextInputFieldFilter.js\",\n            \"admin/js/jquery.init.js\",\n        ]\n\n```\n\n### <a name=\"django_power_admin.filters.DateRangeFilter\"></a>django_power_admin.filters.DateRangeFilter\n\n#### django_power_admin.filters.DateRangeFilter\u6548\u679c\u9884\u89c8\n\n![django_power_admin.filters.DateRangeFilter](https://github.com/zencore-dobetter/pypi-images/raw/main/django-power-admin/filters/DateRangeFilter/DateRangeFilter.png)\n\n\n#### django_power_admin.filters.DateRangeFilter\u4f7f\u7528\u65b9\u5f0f\n\n```\nfrom django.contrib import admin\nfrom django_power_admin.filters import DateRangeFilter\n\nclass ExampleAdmin(admin.ModelAdmin):\n    list_filter = [\n        \"username\",\n        (\"date_join\", DateRangeFilter),\n        \"is_active\",\n    ]\n    list_display = [\"username\", \"date_join\", \"is_active\"]\n```\n\n### Admin\u6837\u5f0f\u7c7b\n\n- inline-narror-input\n\n    TabularInline\u5b57\u7b26\u4e32\u8f93\u5165\u6846\u6539\u4e3a\u5c0f\u6846\u3002\n\n    *\u4f7f\u7528\u8303\u56f4\uff1a*\n\n    - \u53ef\u52a0\u5728TabularInline\u7c7b\u7684claases\u5c5e\u6027\u4e2d\u3002\n\n- related-actions-hidden\n\n    \u9690\u85cf\u5916\u952e\u7684\u589e\u6539\u5220\u6309\u94ae\u3002\n\n    *\u4f7f\u7528\u8303\u56f4\uff1a*\n\n    - \u53ef\u52a0\u5728fieldsets\u7684classes\u5c5e\u6027\u4e2d\u3002\n    - \u53ef\u4ee5\u52a0\u5728TabularInline\u7c7b\u7684claases\u5c5e\u6027\u4e2d\u3002\n\n- inline-original-hidden\n\n    \u9690\u85cfTabularInline\u53caStackInline\u4e2d\u7684orininal\u663e\u793a\u3002\n\n    *\u4f7f\u7528\u8303\u56f4\uff1a*\n\n    - \u53ef\u52a0\u5728TabularInline\u7c7b\u7684claases\u5c5e\u6027\u4e2d\u3002\n    - \u53ef\u52a0\u5728StackInline\u7c7b\u7684claases\u5c5e\u6027\u4e2d\u3002\n\n- form-row-c2\n\n    FormChange\u8868\u5355\u4e24\u4f8b\u663e\u793a\uff0c\u540c\u65f6\u63a7\u5236textarea\u7684\u5bbd\u5ea6\u3002\n\n    *\u4f7f\u7528\u8303\u56f4\uff1a*\n\n    - \u53ef\u52a0\u5728fieldsets\u7684classes\u5c5e\u6027\u4e2d\u3002\n\n### Admin\u5168\u5c40\u63a7\u5236\n\n- DJANGO_ADMIN_USE_FIXED_WIDTH_LAYOUT\n\n    \u5f53DJANGO_ADMIN_USE_FIXED_WIDTH_LAYOUT=True\uff0cAdmin\u7ba1\u7406\u540e\u53f0\u8bbe\u7f6e\u4e3a\u56fa\u5b9a\u5bbd\u5ea6\uff0c\u4e14\u5c45\u4e2d\u663e\u793a\u3002\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8bbe\u7f6e\u63a7\u5236\u5bbd\u5ea6\u53ca\u80cc\u666f\u8272\u3002\n\n    *\u5173\u8054\u8bbe\u7f6e\u9879\uff1a*\n\n    - DJANGO_ADMIN_USE_FIXED_WIDTH_LAYOUT = False\n    - DJANGO_ADMIN_WIDTH = 1280px\n    - DJANGO_ADMIN_BACKGROUND_COLOR = \"#f5f6f8\"\n    - DJANGO_ADMIN_FOOTER_COLOR = \"#c5cbd2\"\n\n\n## \u7248\u672c\u8bb0\u5f55\n\n### v0.1.7\n\n- \u9879\u76ee\u542f\u52a8\u3002\n- \u6846\u67b6\u642d\u5efa\u3002\n- PowerAdmin\u7c7b\u57fa\u672c\u5b8c\u6210\u3002\n\n### v0.1.10\n\n- get_extra_views\u66f4\u540d\u4e3aget_extra_view_urls\uff0c\u907f\u514d\u4e0e\u5176\u5b83\u65b9\u6cd5\u540d\u51b2\u7a81\u3002\n- view_action\u66f4\u540d\u4e3aread_xxx\u3002xxx_action\u66f4\u540d\u4e3axxx_button\u3002\n- \u5728list_display\u4e2d\u8ffd\u52a0change_list_object_toolbar\u5b57\u6bb5\u3002\n\n### v0.1.12\n\n- \u589e\u52a0has_change_permission_real, has_delete_permission_real\u65b9\u6cd5\uff0c\u89e3\u51b3read/change\u673a\u5236\u5bfc\u81f4\u7684\u539f\u59cb\u6743\u9650\u5224\u65ad\u4e22\u5931\u7684\u60c5\u51b5\u3002\n- \u589e\u52a0get_messages\u65b9\u6cd5\uff0c \u7528\u4e8e\u83b7\u53d6\u7ad9\u70b9\u5f53\u524d\u7684messages\u961f\u5217\u3002\n- \u589e\u52a0get_power_admin_class\uff0c\u7528\u4e8e\u7edf\u4e00\u6269\u5c55\u6240\u6709PowerAdmin\u7684\u5b50\u7c7b\u3002\n\n### v0.1.18\n\n- \u4fee\u6b63get_changelist_object_row_classes_javascript\u65b9\u6cd5\u5728\u9047\u5230\u5176\u5b83\u9519\u8bef\u65f6\u5bfc\u81f4\u7684\u5f02\u5e38\u884c\u4e3a\u3002\n- ChangelistObjectToolbarButton\u53ef\u4ee5\u76f4\u63a5\u5f15\u7528extra view\uff08\u9700\u8981\u4e3aextra view\u6dfb\u52a0\u6309\u94ae\u989d\u5916\u5c5e\u6027\uff0c\u5982\uff1ashort_description\u3001icon\u3001classes\u7b49\uff09\u3002\n- change_list_xxx\u66f4\u540d\u4e3achangelist_xxx\uff08\u6ce8\u610f\uff1a\u53ef\u80fd\u5f15\u8d77\u65b0\u65e7\u7248\u672c\u7684\u4e0d\u517c\u5bb9\uff0c\u7279\u522b\u662f\u5b50\u7c7b\u914d\u7f6e\u7684change_list_toolbar_buttons\u5c5e\u6027\u9700\u8981\u6539\u540d\u4e3achangelist_toolbar_buttons\uff09\u3002\n- \u5f15\u5165ChangelistToolbar\u673a\u5236\uff0c\u7528\u4e8e\u6dfb\u52a0\u989d\u5916\u7684\u5217\u8868\u9875\u9876\u90e8\u6309\u94ae\u3002\n\n### v0.1.20\n\n- \u6dfb\u52a0\u7b80\u6613\u6570\u636e\u5206\u4eab\u673a\u5236\u7684\u652f\u6301\uff08simple share model\uff09\u3002\n- \u6dfb\u52a0\u6570\u636e\u5bfc\u51fa\u529f\u80fd\u3002\n\n### v0.1.21\n\n- \u6dfb\u52a0\u9002\u7528\u4e8eTextField\u4f7f\u7528\u7684\u201c\u952e\u503c\u5bf9\u201d\u63a7\u4ef6\u3002\n- PowerAdmin\u4e2d\u65b9\u6cd5\u540d\u52a0\u4e0adjango_power_admin_\u524d\u7f00\uff0c\u907f\u514d\u4e0e\u5176\u5b83\u6269\u5c55\u7c7b\u51b2\u7a81\u3002\n\n### v0.1.23\n\n- \u4fee\u6b63Select2\u3001SelectMultiple2\u3001ConfigTable\u5728inline\u8868\u5355\u4e2d\u7684\u4f7f\u7528\u95ee\u9898\u3002\n- \u65b0\u589edjango_power_admin.widgets.AllUsersSelect\u3002\n\n### v0.1.24\n\n- \u65b0\u589edjango_power_admin.filters.TextInputFieldFilter\u3002\n- \u65b0\u589elist_filter\u7c7b\u901a\u8fc7\u5b9a\u4e49\u5185\u90e8\u7684`Media:`\u5f15\u5165\u989d\u5916\u7684js/css\u6587\u4ef6\u7684\u673a\u5236\u3002\n\n### v0.1.25\n\n- \u65b0\u589edjango_power_admin.filters.DateRangeFilter\u3002\n\n### v0.1.27\n\n- \u4fee\u6b63ChangelistObjectToolbar\u6309\u94ae\u6362\u884c\u7684\u95ee\u9898\u3002\n\n### v0.1.29\n\n- \u517c\u5bb9django 4.x\u3002\n- \u517c\u5bb9python 2.7\u3002\n- \u4fee\u6b63\u6392\u5e8fAdmin\u672a\u8bbe\u7f6eordering\u65f6\u7684\u5f02\u5e38\u3002\n\n### v0.1.30\n\n- \u4fee\u6b63get_ordering\u5f3a\u5236\u6dfb\u52a0display_order\u5b57\u6bb5\u5bfc\u81f4\u7684\u95ee\u9898\u3002\n\n### v0.1.31\n\n- \u4fee\u6b63ChangelistObjectToolBarButton\u7684\u9ed8\u8ba4target=self\u95ee\u9898\uff0c\u4fee\u6b63\u540e\u7684\u9ed8\u8ba4target=_self\u3002\n- \u4f7f\u7528zenutils\u4f9d\u8d56\u5305\u4ee5\u7b80\u5316\u4e0d\u5fc5\u8981\u7684\u4f9d\u8d56\u5173\u7cfb\u3002\n\n### v0.1.35\n\n- \u4fee\u6b63DateRangeFilter\u7ed3\u675f\u65e5\u671f\u6846\u641c\u7d22\u6761\u4ef6\u540d\u79f0\u9519\u8bef\u7684\u95ee\u9898\u3002\n\n### v0.1.36\n\n- \u589e\u52a0\u7ad9\u70b9\u56fa\u5b9a\u5bbd\u5ea6\u5c45\u4e2d\u3002\n- \u589e\u52a0Admin\u6837\u5f0f\u7c7b\uff1aform-row-c2\u3001inline-original-hidden\u3001related-actions-hidden\u3001inline-narror-input\u3002\n- \u589e\u52a0PopupConfigTable\u63a7\u4ef6\u3002\n\n### v0.1.37\n\n- \u6587\u6863\u66f4\u65b0\u3002\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Django\u63d0\u4f9b\u4e86\u5feb\u6377\u7684\u751f\u6210\u540e\u53f0\u7ba1\u7406\u7ad9\u70b9\u7684\u80fd\u529b\u3002\u672c\u5e94\u7528\u65e8\u5728\u589e\u5f3aDjango Admin\u7684\u80fd\u529b\uff0c\u63d0\u4f9b\u4e30\u5bcc\u7684Admin\u3001Widget\u3001ListFilter\u3001Form\u7b49\u7b49\u754c\u9762\u6269\u5c55\u7c7b\uff0c\u540c\u65f6\u4e5f\u4e3a\u5e38\u7528\u7684\u6570\u636e\u7ba1\u7406\u6a21\u578b\u63d0\u4f9b\u5b8c\u6574\u7684\u7ba1\u7406\u529f\u80fd\u3002",
    "version": "0.1.37",
    "project_urls": null,
    "split_keywords": [
        "django",
        "django admin",
        "django power admin",
        "django admin extensions"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bf3023f2b785dfeb5e10262a8090086b9d13d04eb699edd614ebc248a7645db7",
                "md5": "37bf5c121aadc53c13cdfac3a86c4152",
                "sha256": "87aeb34d9e447b2f738d344c1682a6e38f2bf07b2853dd4b1e6f28a1d912f214"
            },
            "downloads": -1,
            "filename": "django_power_admin-0.1.37-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "37bf5c121aadc53c13cdfac3a86c4152",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 50282,
            "upload_time": "2023-09-14T12:41:45",
            "upload_time_iso_8601": "2023-09-14T12:41:45.446381Z",
            "url": "https://files.pythonhosted.org/packages/bf/30/23f2b785dfeb5e10262a8090086b9d13d04eb699edd614ebc248a7645db7/django_power_admin-0.1.37-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ca5b18440bf9b0a538d109be7e4db1188e999f5b3db4668d0822a1f2eba99073",
                "md5": "379cb99443847ef00aa147432211d465",
                "sha256": "fe34b7b1865c47780dac4ed2cd76beb36ee9b276bd0baa25b6e4adb15bbb1c37"
            },
            "downloads": -1,
            "filename": "django-power-admin-0.1.37.tar.gz",
            "has_sig": false,
            "md5_digest": "379cb99443847ef00aa147432211d465",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 42746,
            "upload_time": "2023-09-14T12:41:48",
            "upload_time_iso_8601": "2023-09-14T12:41:48.259187Z",
            "url": "https://files.pythonhosted.org/packages/ca/5b/18440bf9b0a538d109be7e4db1188e999f5b3db4668d0822a1f2eba99073/django-power-admin-0.1.37.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-14 12:41:48",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "django-power-admin"
}
        
Elapsed time: 0.54616s