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

不言
Libérer: 2018-05-04 14:26:59
original
1698 Les gens l'ont consulté

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"
]
Copier après la connexion

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

]
Copier après la connexion

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
Copier après la connexion

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)
Copier après la connexion

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) # 第一个参数可以是列表
Copier après la connexion

Méthode 2 :


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

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"
Copier après la connexion

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',)
Copier après la connexion

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',)
Copier après la connexion

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

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  search_fields = ('user', 'pwd')
Copier après la connexion

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

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  date_hierarchy = 'ctime'
Copier après la connexion

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, ]
Copier après la connexion

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
Copier après la connexion

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
Copier après la connexion

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字段',)
Copier après la connexion

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

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  fields = ('user',)
Copier après la connexion

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

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  exclude = ('user',)
Copier après la connexion

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

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
  readonly_fields = ('user',)
Copier après la connexion

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'),
    }),
  )
Copier après la connexion

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字段",)
Copier après la connexion

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', ]
Copier après la connexion

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

radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL
Copier après la connexion

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
Copier après la connexion

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 = "指定列数据为空时,默认显示"
Copier après la connexion

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)
Copier après la connexion

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
Copier après la connexion

在上面的代码中,我们将类的实例和一个类变量 _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()
Copier après la connexion

将上面的代码保存在文件 mysingleton.py 中,然后这样使用:

from mysingleton import my_singleton
my_singleton.foo()
Copier après la connexion

admin执行流程

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

def autodiscover():
  autodiscover_modules(&#39;admin&#39;, register_to=site)
Copier après la connexion

<2> 执行代码

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

admin.site.register(Book, BookAdmin) 
admin.site.register(Publish)
Copier après la connexion

<3> admin.site

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

<4> 执行register方法

admin.site.register(Book, BookAdmin) 
admin.site.register(Publish)
Copier après la connexion

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)
Copier après la connexion

到这里,注册结束!

<5> admin的URL配置

urlpatterns = [
  url(r&#39;^admin/&#39;, admin.site.urls),
]
Copier après la connexion

class AdminSite(object):  
   def get_urls(self):
    from django.conf.urls import url, include   
    urlpatterns = []
    # Add in each model&#39;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&#39;^%s/%s/&#39; % (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(), &#39;admin&#39;, self.name
Copier après la connexion

<6> url()方法的扩展应用

from django.shortcuts import HttpResponse
def test01(request):
  return HttpResponse("test01")

def test02(request):
  return HttpResponse("test02")

urlpatterns = [
  url(r&#39;^admin/&#39;, admin.site.urls),
  url(r&#39;^yuan/&#39;, ([
          url(r&#39;^test01/&#39;, test01),
          url(r&#39;^test02/&#39;, test02),

          ],None,None)),

]
Copier après la connexion

扩展优化

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&#39;^admin/&#39;, admin.site.urls),
  url(r&#39;^yuan/&#39;, (url_list,None,None)),
]
Copier après la connexion

仿admin的url路径分发

#############models.py###########
from django.db import models
class Book(models.Model):
  title = models.CharField(max_length=32)
  author = models.ForeignKey(to=&#39;Author&#39;)
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(&#39;add&#39;)
def change(request,id):
  return HttpResponse(&#39;change&#39;)
def delete(request,id):
  return HttpResponse(&#39;delete&#39;)
def show(request):
  return HttpResponse(&#39;show&#39;)
################url.py##############
def get_urls2():
  tmp = []
  tmp.append(url(r&#39;^add/&#39;,add))
  tmp.append(url(r&#39;^(\d+)/change/&#39;,change))
  tmp.append(url(r&#39;^(\d+)/delete/&#39;,delete))
  tmp.append(url(r&#39;^&#39;,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&#39;^{}/{}/&#39;.format(app_label,model_name),(get_urls2(),None,None))) #[url(r&#39;^app01/book/&#39;,),]
  return temp

urlpatterns = [
  url(r&#39;^admin/&#39;, (get_urls(), None, None)),
  url(r&#39;^admin/&#39;, admin.site.urls),
]
Copier après la connexion

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!