Maison  >  Article  >  développement back-end  >  Explication détaillée de l'utilisation et analyse du code source du composant admin de Django

Explication détaillée de l'utilisation et analyse du code source du composant admin de Django

不言
不言original
2018-05-04 14:26:591696parcourir

Cet article présente principalement en détail l'utilisation et l'analyse du code source du composant admin de Django. Maintenant, je le partage avec vous. Les amis dans le besoin peuvent se référer au

Composant admin Utilisation de

Django fournit des outils de gestion basés sur le Web.

Les outils de gestion automatisée de Django font partie de django.contrib. Vous pouvez le voir dans INSTALLED_APPS dans les paramètres du projet.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 est un énorme ensemble de fonctionnalités pour les composants Django du code de base.

Outil de gestion des activations

Habituellement, nous le définirons automatiquement dans urls.py lors de la génération du projet,

from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
  url(r'^admin/', admin.site.urls),

]

Une fois tout configuré, l'outil d'administration Django est prêt à fonctionner.

Utilisez l'outil de gestion

Démarrez le serveur de développement, puis visitez http://127.0.0.1:8000/admin/ dans le navigateur pour obtenir l'interface de connexion . Vous pouvez créer un superutilisateur via la commande python manage.py createsuperuser.

Pour que l'interface d'administration puisse gérer un certain modèle de données, nous devons d'abord enregistrer le modèle de données auprès de l'administrateur

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

Personnalisation de l'administrateur

Dans admin.py, il vous suffit d'enregistrer une certaine classe dans Mode pour réaliser la fonction d'ajout, de suppression, de modification et d'archivage dans Admin, telle que :

admin.site.register(models.UserInfo)

Cependant, cette méthode est relativement simple si vous souhaitez effectuer plus d'opérations de personnalisation, vous devez utiliser ModelAdmin pour fonctionner, comme :

Méthode 1 :


class UserAdmin(admin.ModelAdmin):
   list_display = ('user', 'pwd',)
 
admin.site.register(models.UserInfo, UserAdmin) # 第一个参数可以是列表

Méthode 2 :


@admin.register(models.UserInfo)        # 第一个参数可以是列表
class UserAdmin(admin.ModelAdmin):
  list_display = ('user', 'pwd',)

ModelAdmin Fournit un grand nombre de fonctions personnalisables, telles que

1 list_display, lors du listing, personnalisez les colonnes affichées.

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  list_display = ('user', 'pwd', 'xxxxx')
 
  def xxxxx(self, obj):
    return "xxxxx"

2. list_display_links, lors de la liste, vous pouvez cliquer pour accéder à la colonne personnalisée.

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  list_display = ('user', 'pwd', 'xxxxx')
  list_display_links = ('pwd',)

3. list_filter, lors de la liste, personnalisez le filtre rapide sur le côté droit.

4. list_select_rated, lors de la création d'une liste, si la requête de jointure de table sélectionnera automatiquement_rated

5. lors de la création d'une liste, les colonnes qui peuvent être modifiées

.

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  list_display = ('user', 'pwd','ug',)
  list_editable = ('ug',)

6. search_fields, dans la liste, fonction de recherche floue

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  search_fields = ('user', 'pwd')

7. , lorsque dans la liste, pour la recherche Date et DateTime Type

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  date_hierarchy = 'ctime'

8 inlines, page détaillée, s'il y a d'autres tables faisant FK avec la table actuelle, puis la page détaillée peut être ajoutée et supprimée dynamiquement

class UserInfoInline(admin.StackedInline): # TabularInline
  extra = 0
  model = models.UserInfo
 
class GroupAdminMode(admin.ModelAdmin):
  list_display = ('id', 'title',)
  inlines = [UserInfoInline, ]

9 action, lors du listing, personnaliser l'opération dans l'action

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
 
  # 定制Action行为具体方法
  def func(self, request, queryset):
    print(self, request, queryset)
    print(request.POST.getlist('_selected_action'))
 
  func.short_description = "中文显示自定义Actions"
  actions = [func, ]
 
  # Action选项都是在页面上方显示
  actions_on_top = True
  # Action选项都是在页面下方显示
  actions_on_bottom = False
 
  # 是否显示选择个数
  actions_selection_counter = True

10 Modèle HTML personnalisé

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, page détaillée, pour les champs FK et M2M devenir Formulaire de zone de saisie

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  raw_id_fields = ('FK字段', 'M2M字段',)

12 champs, sur la page détaillée, les champs des champs affichés

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  fields = ('user',)

13 exclure, Sur la page détaillée, champs exclus

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  exclude = ('user',)

14 readonly_fields, sur la page détaillée, lire -champs uniquement

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  readonly_fields = ('user',)

15 champs, sur la page détaillée, utilisez la balise champsets pour diviser et afficher les données

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  fieldsets = (
    ('基本数据', {
      'fields': ('user', 'pwd', 'ctime',)
    }),
    ('其他', {
      'classes': ('collapse', 'wide', 'extrapretty'), # 'collapse','wide', 'extrapretty'
      'fields': ('user', 'pwd'),
    }),
  )

16 sur la page détaillée, Lorsque M2M est affiché, sélection du mouvement des données (direction : haut, bas et gauche et droite)

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)

17 commande, lors du listing, règle de tri des données

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  ordering = ('-id',)
  或
  def get_ordering(self, request):
    return ['-id', ]

18. l'option d'affichage radio (FK utilise select par défaut)

radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL

19 form = ModelForm, utilisé pour personnaliser la validation du formulaire lorsque l'utilisateur le demande

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 = "Lorsque les données de la colonne sont vides, affichez la valeur par défaut "

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  empty_value_display = "列数据为空时,默认显示"
 
  list_display = ('user','pwd','up')
 
  def up(self,obj):
    return obj.user
  up.empty_value_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)
  # 定制Action行为具体方法
  def func(self, request, queryset):
    print(self, request, queryset)
    print(request.POST.getlist('_selected_action'))

  func.short_description = "中文显示自定义Actions"
  actions = [func, ]
  # Action选项都是在页面上方显示
  actions_on_top = True
  # Action选项都是在页面下方显示
  actions_on_bottom = False

  # 是否显示选择个数
  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) # 第一个参数可以是列表
admin.site.register(Publish,PublishAdmin)
admin.site.register(Author)

analyse du code source de l'administrateur

Singleton Pattern

Singleton Pattern est une conception logicielle couramment utilisée modèle L'objectif principal de ce modèle est de garantir qu'une seule instance d'une certaine classe existe. Les objets Singleton sont utiles lorsque vous souhaitez qu'une seule instance d'une certaine classe apparaisse dans l'ensemble du système.

Par exemple, les informations de configuration d'un programme serveur sont stockées dans un fichier et le client lit les informations du fichier de configuration via une classe AppConfig. Si le contenu du fichier de configuration doit être utilisé à plusieurs endroits lors de l'exécution du programme, c'est-à-dire que des instances de l'objet AppConfig doivent être créées à plusieurs endroits, ce qui conduira à l'existence de plusieurs objets d'instance AppConfig. dans le système, ce qui gaspillera sérieusement les ressources de mémoire, surtout si le fichier de configuration contient beaucoup de contenu. En fait, pour une classe comme AppConfig, nous espérons qu'un seul objet instance existe pendant l'exécution du programme.

En Python, nous pouvons utiliser diverses méthodes pour implémenter le modèle singleton :

  1. Utiliser des modules

  2. Utiliser __new__

  3. Utiliser le décorateur

  4. Utiliser la métaclasse

(1) en utilisant __new__

为了使类只能出现一个实例,我们可以使用 __new__ 来控制实例的创建过程,代码如下:

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 关联起来,如果  cls._instance 为 None 则创建实例,否则直接返回  cls._instance 。

执行情况如下:

>>> one = MyClass()
>>> two = MyClass()
>>> one == two
True
>>> one is two
True
>>> id(one), id(two)
(4303862608, 4303862608)

(2)使用模块

其实, Python 的模块就是天然的单例模式 ,因为模块在第一次导入时,会生成  .pyc 文件,当第二次导入时,就会直接加载  .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

# 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执行流程

f35d6e602fd7d0f0edfa6f7d103c1b57 循环加载执行所有已经注册的app中的admin.py文件

def autodiscover():
  autodiscover_modules('admin', register_to=site)

2cc198a1d5eb0d3eb508d858c9f5cbdb 执行代码

#admin.py
class BookAdmin(admin.ModelAdmin):
  list_display = ("title",'publishDate', 'price')

admin.site.register(Book, BookAdmin) 
admin.site.register(Publish)

5bdf4c78156c7953567bb5a0aef2fc53 admin.site

这里应用的是一个单例模式,对于AdminSite类的一个单例模式,执行的每一个app中的每一个admin.site都是一个对象

23889872c2e8594e0f446a471a78ec4c 执行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)

到这里,注册结束!

43ad812d3a971134e40facaca816c822 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

efbfa0de8737dc86eae413541a49df20  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)),
]

仿admin的url路径分发

#############models.py###########
from django.db import models
class Book(models.Model):
  title = models.CharField(max_length=32)
  author = models.ForeignKey(to='Author')
class Author(models.Model):
  name = models.CharField(max_length=32)
#################admin.py###########
from app01.models import *
admin.site.register(Book)
admin.site.register(Author)
##############views.py################
from django.shortcuts import HttpResponse
def add(request):
  return HttpResponse('add')
def change(request,id):
  return HttpResponse('change')
def delete(request,id):
  return HttpResponse('delete')
def show(request):
  return HttpResponse('show')
################url.py##############
def get_urls2():
  tmp = []
  tmp.append(url(r'^add/',add))
  tmp.append(url(r'^(\d+)/change/',change))
  tmp.append(url(r'^(\d+)/delete/',delete))
  tmp.append(url(r'^',show))
  return tmp
def get_urls():
  temp = []
  for model, admin_class_obj in admin.site._registry.items():
    model_name = model._meta.model_name
    app_label = model._meta.app_label
    temp.append(url(r'^{}/{}/'.format(app_label,model_name),(get_urls2(),None,None))) #[url(r'^app01/book/',),]
  return temp

urlpatterns = [
  url(r'^admin/', (get_urls(), None, None)),
  url(r'^admin/', admin.site.urls),
]

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn