Heim >Backend-Entwicklung >Python-Tutorial >Detaillierte Erläuterung der Verwendung und Quellcode-Analyse der Admin-Komponente von Django

Detaillierte Erläuterung der Verwendung und Quellcode-Analyse der Admin-Komponente von Django

不言
不言Original
2018-05-04 14:26:591721Durchsuche

Dieser Artikel stellt hauptsächlich die Verwendung und Quellcode-Analyse der Admin-Komponente von Django vor. Jetzt kann ich ihn mit Ihnen teilen

admin-Komponente Mit

Django bietet webbasierte Verwaltungstools.

Djangos automatisierte Verwaltungstools sind Teil von django.contrib. Sie können es in INSTALLED_APPS in der Datei „settings.py“ des Projekts sehen:

# 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 ist ein riesiger Funktionssatz, der aus den Django-Basiscodekomponenten besteht.

Aktivierungsverwaltungstool

Normalerweise legen wir es automatisch in urls.py fest, wenn wir das Projekt generieren,

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

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

]

Sobald dies alles konfiguriert ist, ist das Django-Administrationstool betriebsbereit.

Verwenden Sie das Verwaltungstool

Starten Sie den Entwicklungsserver und besuchen Sie dann http://127.0.0.1:8000/admin/ im Browser, um die Anmeldeschnittstelle zu erhalten Sie können einen Superuser über den Befehl python manage.py createsuperuser erstellen.

Damit die Admin-Oberfläche ein bestimmtes Datenmodell verwalten kann, müssen wir das Datenmodell zunächst beim Admin registrieren

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-Anpassung

In admin.py müssen Sie nur eine bestimmte Klasse im Modus registrieren, um die Funktionen zum Hinzufügen, Löschen, Ändern und Einchecken im Admin zu implementieren, wie zum Beispiel:

admin.site.register(models.UserInfo)

Diese Methode ist jedoch relativ einfach. Wenn Sie weitere Anpassungsvorgänge durchführen möchten, müssen Sie ModelAdmin verwenden, z. B.:

Methode 1:

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

Methode 2:

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

ModelAdmin Bietet eine große Anzahl anpassbarer Funktionen, z. B.

1. Passen Sie beim Auflisten die angezeigten Spalten an.

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

2. list_display_links, beim Auflisten können Sie auf klicken, um zur benutzerdefinierten Spalte zu springen.

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

3. Passen Sie beim Auflisten den Schnellfilter auf der rechten Seite an.

4. list_select_related, ob die Join-Tabellenabfrage automatisch ausgewählt wird

5. list_editable, wenn eine Liste bearbeitet werden kann

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

6. Suchfelder, Fuzzy-Suchfunktion in der Liste

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

7. Suche nach Datum und Datum/Uhrzeit Typen in Liste

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

8 Inlines, Detailseite, wenn es andere Tabellen gibt, die FK mit der aktuellen Tabelle ausführen, dann kann die Detailseite dynamisch hinzugefügt und gelöscht werden

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

9 Aktion, passen Sie beim Auflisten den Vorgang in der Aktion an

@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 HTML-Vorlage anpassen

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, detaillierte Seite, für FK- und M2M-Felder werden zum Eingabefeldformular

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

12 Felder, auf der Detailseite die Felder der angezeigten Felder

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

13 ausschließen, auf der Detailseite die Ausgeschlossenen Felder

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

14 readonly_fields, für Detailseiten, schreibgeschützte Felder

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

15 Feldsätze, für detaillierte Seiten verwenden Sie Feldsatz-Tags. Daten werden geteilt und angezeigt

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

16 Bei der Anzeige der Detailseite, M2M, Datenbewegungsauswahl (Richtung: nach oben). , unten und links und rechts)

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

17 Reihenfolge, beim Auflisten, Datensortierregeln

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

18. radio_fields, verwenden Sie beim Anzeigen detaillierter Seiten Radiooptionen (FK verwendet standardmäßig „select“)

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

19 form = ModelForm, wird zum Anpassen verwendet Formularvalidierung bei Benutzeranfragen

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 = „Wenn die Spaltendaten leer sind, wird der Standardwert angezeigt“

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

Administrator-Quellcode-Analyse

Singleton-Muster

Singleton-Muster ist ein Der Hauptzweck dieses Musters besteht darin, sicherzustellen, dass nur eine Instanz einer Klasse vorhanden ist. Singleton-Objekte sind praktisch, wenn im gesamten System nur eine Instanz einer bestimmten Klasse angezeigt werden soll.

Zum Beispiel werden die Konfigurationsinformationen eines Serverprogramms in einer Datei gespeichert und der Client liest die Konfigurationsdateiinformationen über eine AppConfig-Klasse. Wenn der Inhalt der Konfigurationsdatei während der Ausführung des Programms an vielen Stellen verwendet werden muss, müssen also an vielen Stellen Instanzen des AppConfig-Objekts erstellt werden, was zur Existenz mehrerer AppConfig-Instanzobjekte führt im System, und dies führt zu einer erheblichen Speicherverschwendung, insbesondere wenn die Konfigurationsdatei viel Inhalt enthält. Tatsächlich hoffen wir für eine Klasse wie AppConfig, dass nur ein Instanzobjekt vorhanden ist, während das Programm ausgeführt wird.

In Python können wir verschiedene Methoden verwenden, um das Singleton-Muster zu implementieren:

  1. Module verwenden

  2. Verwenden Sie __new__

  3. Verwenden Sie den Dekorator

  4. Verwenden Sie die Metaklasse

(1 ) mit __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),
]

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Verwendung und Quellcode-Analyse der Admin-Komponente von Django. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn