admin component use
Django provides web-based administration tools.
The Django auto-admin tool is part of django.contrib. You can see it in INSTALLED_APPS in your project's settings.py:
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', "app01" ]
django.contrib is a huge feature set that is part of Django's base code.
Activation Management Tool
Usually we will automatically set it in urls.py when we generate the project,
from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), ]
When this is all configured, the Django admin tool is ready to run.
Use management tools
Start the development server, and then visit http://127.0.0.1:8000/admin/ in the browser to get the login interface. You can create a superuser by running the command python manage.py createsuperuser .
In order for the admin interface to manage a data model, we need to first register the data model to the admin
from django.db import models class Author(models.Model): name=models.CharField( max_length=32) age=models.IntegerField() def __str__(self): return self.name class Publish(models.Model): name=models.CharField( max_length=32) email=models.EmailField() def __str__(self): return self.name class Book(models.Model): title = models.CharField( max_length=32) publishDate=models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2) publisher=models.ForeignKey(to="Publish") authors=models.ManyToManyField(to='Author') def __str__(self): return self.title
admin customization
In admin.py, you only need to register a class in Mode, and you can implement the function of adding, deleting, modifying and checking in Admin, such as:
admin.site.register(models.UserInfo)
However, this method is relatively simple. If you want to perform more customized operations, you need to use ModelAdmin to operate, such as:
method one: class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd',) admin.site.register(models.UserInfo, UserAdmin) # The first parameter can be a list Method two: @admin.register(models.UserInfo) # The first parameter can be a list class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd',)
A large number of customizable features are provided in ModelAdmin, such as
1. list_display, when listing, customize the displayed columns.
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd', 'xxxxx') def xxxxx(self, obj): return "xxxxx"
2. list_display_links, in the list, the custom column can be clicked to jump.
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd', 'xxxxx') list_display_links = ('pwd',)
3. list_filter, when listing, customize the quick filter on the right.
4. list_select_related, in the list, whether the query of the connected table will automatically select_related
5. list_editable, the column that can be edited when the list is
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd', 'ug',) list_editable = ('ug',)
6. search_fields, the function of fuzzy search when listing
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): search_fields = ('user', 'pwd')
7. date_hierarchy, when listing, searches for Date and DateTime types
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): date_hierarchy = 'ctime'
8 inlines, detailed page, if there are other tables and the current table for FK, then the detailed page can be dynamically added and deleted
class UserInfoInline(admin.StackedInline): # TabularInline extra = 0 model = models.UserInfo class GroupAdminMode(admin.ModelAdmin): list_display = ('id', 'title',) inlines = [UserInfoInline, ]
9 action, list, customize the action in the action
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): # Customize the specific method of Action behavior def func(self, request, queryset): print(self, request, queryset) print(request.POST.getlist('_selected_action')) func.short_description = "Chinese display custom Actions" actions = [func, ] # Action options are displayed at the top of the page actions_on_top = True # Action options are displayed at the bottom of the page actions_on_bottom = False # Whether to display the number of choices actions_selection_counter = True
10 Custom HTML Templates
add_form_template = None change_form_template = None change_list_template = None delete_confirmation_template = None delete_selected_confirmation_template = None object_history_template = None
11 raw_id_fields, detail page, for FK and M2M fields becomes in the form of Input box
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): raw_id_fields = ('FK field', 'M2M field',)
12 fields, when the detail page, the field of the field is displayed
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): fields = ('user',)
13 exclude, when the detail page, the excluded field
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): exclude = ('user',)
14 readonly_fields, detail page, read-only field
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): readonly_fields = ('user',)
15 fieldsets, when the detailed page is used, use the fieldsets tag to split the data and display
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): fieldsets = ( ('basic data', { 'fields': ('user', 'pwd', 'ctime',) }), ('other', { 'classes': ('collapse', 'wide', 'extrapretty'), # 'collapse','wide', 'extrapretty' 'fields': ('user', 'pwd'), }), )
16 When the detail page is displayed, when M2M is displayed, the data movement selection (direction: up and down and left and right)
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): filter_vertical = ("m2m field",) # or filter_horizontal = ("m2m field",)
17 ordering, list, data sorting rules
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): ordering = ('-id',) or def get_ordering(self, request): return ['-id', ]
18. radio_fields, when detailed page, use radio to display options (FK uses select by default)
radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL
19 form = ModelForm, used to customize form validation when user requests
from app01 import models from django.forms import ModelForm from django.forms import fields class MyForm(ModelForm): others = fields.CharField() class Meta: model = models = models.UserInfo fields = "__all__" @admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): form = MyForm
20 empty_value_display = "When the column data is empty, display the default value"
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): empty_value_display = "Default display when column data is empty" list_display = ('user','pwd','up') def up(self,obj): return obj.user up.empty_value_display = "When the specified column data is empty, the default display"
from django.contrib import admin # Register your models here. from .models import * class BookInline(admin.StackedInline): # TabularInline extra = 0 model = Book class BookAdmin(admin.ModelAdmin): list_display = ("title",'publishDate', 'price',"foo","publisher") list_display_links = ('publishDate',"price") list_filter = ('price',) list_editable=("title","publisher") search_fields = ('title',) date_hierarchy = 'publishDate' preserve_filters=False def foo(self,obj): return obj.title+str(obj.price) # Customize the specific method of Action behavior def func(self, request, queryset): print(self, request, queryset) print(request.POST.getlist('_selected_action')) func.short_description = "Chinese display custom Actions" actions = [func, ] # Action options are displayed at the top of the page actions_on_top = True # Action options are displayed at the bottom of the page actions_on_bottom = False # Whether to display the number of choices actions_selection_counter = True change_list_template="my_change_list_template.html" class PublishAdmin(admin.ModelAdmin): list_display = ('name', 'email',) inlines = [BookInline, ] admin.site.register(Book, BookAdmin) # The first parameter can be a list admin.site.register(Publish,PublishAdmin) admin.site.register(Author)
admin source code analysis
singleton pattern
The Singleton Pattern is a common software design pattern whose main purpose is to ensure that only one instance of a class exists . Singleton objects come in handy when you want only one instance of a class to appear in the entire system.
For example, the configuration information of a server program is stored in a file, and the client reads the configuration file information through an AppConfig class. If the content of the configuration file needs to be used in many places during the running of the program, that is to say, instances of AppConfig objects need to be created in many places, which leads to the existence of multiple AppConfig instance objects in the system, which will seriously waste memory resources, especially if the config file has a lot of content. In fact, for a class like AppConfig, we want only one instance of the object to exist during the runtime of the program.
In Python, we can implement the singleton pattern in several ways:
- Use modules
- use
__new__
- Use decorators
- Using metaclasses
(1) Use __new__
In order to make only one instance of the class appear, we can use __new__
to control the creation process of the instance, the code is as follows:
class Singleton(object): _instance = None def __new__(cls, *args, **kw): if not cls._instance: cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) return cls._instance class MyClass(Singleton): a = 1
_instance
In the above code, we associate the instance of the class with a class variable , if it cls._instance
is None then create the instance, otherwise return it directly cls._instance
.
The implementation is as follows:
>>> one = MyClass() >>> two = MyClass() >>> one == two True >>> one is two True >>> id(one), id(two) (4303862608, 4303862608)
(2) Using modules
In fact, Python's module is a natural singleton mode , because when the module is imported for the first time, it will generate a .pyc
file, and when it is imported for the second time, the .pyc
file will be loaded directly without executing the module code again. Therefore, we only need to define the related functions and data in a module to obtain a singleton object. If we really want a singleton class, consider doing this:
# mysingleton.py class My_Singleton(object): def foo(self): pass my_singleton = My_Singleton()
将上面的代码保存在文件 mysingleton.py
中,然后这样使用:
from mysingleton import my_singleton my_singleton.foo()
admin执行流程
<1> 循环加载执行所有已经注册的app中的admin.py文件
def autodiscover(): autodiscover_modules('admin', register_to=site)
<2> 执行代码
#admin.py class BookAdmin(admin.ModelAdmin): list_display = ("title",'publishDate', 'price') admin.site.register(Book, BookAdmin) admin.site.register(Publish)
<3> admin.site
这里应用的是一个单例模式,对于AdminSite类的一个单例模式,执行的每一个app中的每一个admin.site都是一个对象
<4> 执行register方法
admin.site.register(Book, BookAdmin) admin.site.register(Publish)
class ModelAdmin(BaseModelAdmin):pass def register(self, model_or_iterable, admin_class=None, **options): if not admin_class: admin_class = ModelAdmin # Instantiate the admin class to save in the registry self._registry[model] = admin_class(model, self)
到这里,注册结束!
<5> admin的URL配置
urlpatterns = [ url(r'^admin/', admin.site.urls), ]
class AdminSite(object): def get_urls(self): from django.conf.urls import url, include urlpatterns = [] # Add in each model's views, and create a list of valid URLS for the # app_index valid_app_labels = [] for model, model_admin in self._registry.items(): urlpatterns += [ url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)), ] if model._meta.app_label not in valid_app_labels: valid_app_labels.append(model._meta.app_label) return urlpatterns @property def urls(self): return self.get_urls(), 'admin', self.name
<6> url()方法的扩展应用
from django.shortcuts import HttpResponse def test01(request): return HttpResponse("test01") def test02(request): return HttpResponse("test02") urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^yuan/', ([ url(r'^test01/', test01), url(r'^test02/', test02), ],None,None)), ]
扩展优化
from django.conf.urls import url,include from django.contrib import admin from django.shortcuts import HttpResponse def change_list_view(request): return HttpResponse("change_list_view") def add_view(request): return HttpResponse("add_view") def delete_view(request): return HttpResponse("delete_view") def change_view(request): return HttpResponse("change_view") def get_urls(): temp=[ url(r"^$".format(app_name,model_name),change_list_view), url(r"^add/$".format(app_name,model_name),add_view), url(r"^\d+/del/$".format(app_name,model_name),delete_view), url(r"^\d+/change/$".format(app_name,model_name),change_view), ] return temp url_list=[] for model_class,obj in admin.site._registry.items(): model_name=model_class._meta.model_name app_name=model_class._meta.app_label # temp=url(r"{0}/{1}/".format(app_name,model_name),(get_urls(),None,None)) temp=url(r"{0}/{1}/".format(app_name,model_name),include(get_urls())) url_list.append(temp) urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^yuan/', (url_list,None,None)), ]