创建一个新的django project,新建3个app并进行注册(app01/app02/stark)
luffy_stark/settings.py
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'app02.apps.App02Config', 'stark.apps.StarkConfig', ]
创建基础业务表
app01/models.py
from django.db import models # Create your models here. class Depart(models.Model): """部门表""" title = models.CharField( verbose_name="部门名称", max_length=32, ) class UserInfo(models.Model): """用户表""" name = models.CharField( verbose_name="姓名", max_length=32, ) age = models.CharField( verbose_name="年龄", max_length=32, ) email = models.CharField( verbose_name="邮箱", max_length=32, ) depart = models.ForeignKey( verbose_name="部门", to="Depart", on_delete=models.CASCADE, )
app02/models.py
from django.db import models # Create your models here. class Host(models.Model): """主机表""" host = models.CharField( verbose_name="主机名称", max_length=32, ) ip = models.GenericIPAddressField( verbose_name="ip", protocol="both", )
在stark app下的apps.py中书写ready方法
stark/apps.py
from django.apps import AppConfig from django.utils.module_loading import autodiscover_modules class StarkConfig(AppConfig): name = 'stark' def ready(self): autodiscover_modules("stark")
在stark app下的service目录下的v1.py书写一个类,该类有4个方法,第一个__init__初始化方法为实例绑定了3个变量,第二个register方法为每个models中的数据表类及处理请求的视图函数的类构建成一个字典放入到实例变量中的列表,第三个get_urls方法自动为每个models中的数据表类生成URL并绑定对应的视图函数,数据格式为路由格式,添加到一个列表中,第四个urls方法返回一个含有3个元素的元组,第一个元素为get_urls方法返回的列表,该列表有子路由,第二个元素为实例变量所定义的app_name,第三个元素为实例变量所定义的namespace
stark/service/v1.py
from django.urls import re_path class StarkSite(object): def __init__(self): self._registry = [] self.app_name = "stark" self.namespace = "stark" def register(self, model_class, handler_class): """ :param model_class: 是models中的数据库相关的类 :param handler_class: 处理请求的视图函数所在的类 :return: """ self._registry.append({"model_class": model_class, "handler_class": handler_class(model_class),}) """ self._registry = [ {"model_class": models.Depart, "handler_class": DepartHandler(models.Depart)}, {"model_class": models.UserInfo, "handler_class": UserInfoHandler(models.UserInfo)}, {"model_class": models.Host, "handler_class": HostHandler(models.Host)}, ] """ def get_urls(self): patterns = [] for item in self._registry: model_class = item["model_class"] handler = item["handler_class"] # model_class._meta.app_label = app01/app01/app02/app02 # model_class._meta.model_name = depart/userinfo/host/role app_label, model_name = model_class._meta.app_label, model_class._meta.model_name patterns.append(re_path(r'^%s/%s/list/$' % (app_label, model_name), handler.changelist_view),) patterns.append(re_path(r'^%s/%s/add/$' % (app_label, model_name), handler.add_view),) patterns.append(re_path(r'^%s/%s/change/(\d+)/$' % (app_label, model_name), handler.change_view),) patterns.append(re_path(r'^%s/%s/del/(\d+)/$' % (app_label, model_name), handler.delete_view),) return patterns @property def urls(self): return self.get_urls(), self.app_name, self.namespace site = StarkSite() """ patterns = [ <URLPattern '^app01/depart/list/$'>, <URLPattern '^app01/depart/add/$'>, <URLPattern '^app01/depart/change/(\d+)/$'>, <URLPattern '^app01/depart/del/(\d+)/$'>, <URLPattern '^app01/userinfo/list/$'>, <URLPattern '^app01/userinfo/add/$'>, <URLPattern '^app01/userinfo/change/(\d+)/$'>, <URLPattern '^app01/userinfo/del/(\d+)/$'>, <URLPattern '^app02/host/list/$'>, <URLPattern '^app02/host/add/$'>, <URLPattern '^app02/host/change/(\d+)/$'>, <URLPattern '^app02/host/del/(\d+)/$'>, ] """
app01/stark.py
from stark.service.v1 import site from app01 import models from django.shortcuts import HttpResponse class DepartHandler(object): def __init__(self, model_class): self.model_class = model_class def changelist_view(self, request): """ 列表页面 :param request: :return: """ return HttpResponse("部门列表页面") def add_view(self, request): """ 添加页面 :param request: :return: """ pass def change_view(self,request, pk): """ 编辑页面 :param request: :param pk: :return: """ pass def delete_view(self, request, pk): """ 删除页面 :param request: :param pk: :return: """ pass class UserInfoHandler(object): def __init__(self, model_class): self.model_class = model_class def changelist_view(self, request): """ 列表页面 :param request: :return: """ return HttpResponse("用户列表页面") def add_view(self, request): """ 添加页面 :param request: :return: """ pass def change_view(self,request, pk): """ 编辑页面 :param request: :param pk: :return: """ pass def delete_view(self, request, pk): """ 删除页面 :param request: :param pk: :return: """ pass site.register(models.Depart, DepartHandler) site.register(models.UserInfo, UserInfoHandler)
app02/stark.py
from stark.service.v1 import site from app02 import models from django.shortcuts import HttpResponse class HostHandler(object): def __init__(self, model_class): self.model_class = model_class def changelist_view(self, request): """ 列表页面 :param request: :return: """ return HttpResponse("主机列表页面") def add_view(self, request): """ 添加页面 :param request: :return: """ pass def change_view(self,request, pk): """ 编辑页面 :param request: :param pk: :return: """ pass def delete_view(self, request, pk): """ 删除页面 :param request: :param pk: :return: """ pass site.register(models.Host, HostHandler)
luffy_stark/urls.py
from django.contrib import admin from django.urls import path, re_path from stark.service.v1 import site urlpatterns = [ path('admin/', admin.site.urls), re_path(r'^stark/', site.urls), ]
将数据库迁移好后,启动django项目(在修改配置中加入--noreload),浏览器输入路由查看
此时,已经能够自动生成URL了,我们再新建一个model类看一下,在app02下的models.py中新建一个Role类
app02/models.py
from django.db import models class Role(models.Model): """角色""" title = models.CharField( verbose_name="角色名称", max_length=32, )
app02/stark.py
from stark.service.v1 import site from app02 import models from django.shortcuts import HttpResponse class RoleHandler(object): def __init__(self, model_class): self.model_class = model_class def changelist_view(self, request): """ 列表页面 :param request: :return: """ return HttpResponse("角色列表页面") def add_view(self, request): """ 添加页面 :param request: :return: """ pass def change_view(self,request, pk): """ 编辑页面 :param request: :param pk: :return: """ pass def delete_view(self, request, pk): """ 删除页面 :param request: :param pk: :return: """ pass site.register(models.Role, RoleHandler)
做数据库迁移,python manage.py makemigrations/python manage.py migrate,然后重新启动django项目,查看是否为Role数据表类自动创建了URL
程序运行逻辑:在django项目启动后,路由加载前,会执行app01和app02目录下的stark.py文件,而这两个stark.py文件都各自定义了models.py中数据表类所对应的视图函数,然后利用单例模式,调用了v1.py中实例化的site,并调用了site.register方法,该方法往实例变量self._registry(空列表)中添加元素,且该元素为字典格式,字典里自定义了两个键,第一个键为model_class,值为models.py中的数据表类,第二个键为handler_class,值为一个类,该类的方法为视图函数,需传入一个参数,参数为models.py中的数据表类,传入该参后方便对数据表进行增删改查等操作;总路由加载时,也调用了v1.py中实例化的site,并调用了site.urls静态方法,该方法返回值与include一样,但返回的第一个元素为调用自身的self.get_urls()方法,get_urls方法定义了一个patterns空列表,然后循环实例变量self._registry,每循环一次就往patterns列表中添加四个值,这四个值就是每张数据表所对应的url,每个url都对应了不同的视图函数