Package: django-faster
django-fasterdjango-faster 10行代码实现一张表的增删改查1 知识储备1.1 创建项目创建django项目创建一个空文件夹，用户存放django项目django-adminstartprojectfaster# faster 是项目名称创建两个django appcdfaster

pythonmanage.pystartappfastpythonmanage.pystartapptestapp创建成功后的项目目录结构--demo--faster--fast--migrations--__init__.py--admin.py--apps.py--models.py--tests.py--views.py--testapp--migrations--__init__.py--admin.py--apps.py--models.py--tests.py--views.py--faster--__init__.py--asgi.py--settings.py--urls.py--wsgi.py--manage.py1.2 django程序启动前预留的钩子faster/testapp/apps/fromdjango.appsimportAppConfigclassTestappConfig(AppConfig):default_auto_field="django.db.models.BigAutoField"name="testapp"classAppConfig:defready(self):"""Override this method in subclasses to run code when Django starts.在子类重写这个方法，当django启动时，执行这个方法中的代码"""测试classTestappConfig(AppConfig):default_auto_field="django.db.models.BigAutoField"name="testapp"defready(self):print('django启动前我被执行了')F:\auth_demo\faster\testapp\apps.pychanged,reloading.
django启动前我被执行了
WatchingforfilechangeswithStatReloader
Performingsystemchecks...

Systemcheckidentifiednoissues(0silenced).

Youhave18unappliedmigration(s).Yourprojectmaynotworkproperlyuntilyouapplythemigrationsforapp(s):admin,auth,contenttypes,sessions.
Run'python manage.py migrate'toapplythem.
September11,2022-10:46:56
Djangoversion4.1.1,usingsettings'faster.settings'Startingdevelopmentserverathttp://127.0.0.1:8000/
QuittheserverwithCTRL-BREAK.1.3 django路由分发的本质首先说一下视图的类型，从视图的类型划分，有CBV和FBV即类视图和函数视图，一般类视图适合用于生成restful风格的API。函数视图使用比较简单。1.3.1 路由的两种基本使用方式：方式一：这是最简单的路由设置，直接在项目文件夹下面的urls.py中配置路由规则和视图函数，浏览器访问http://127.0.0.1:8000/test/就会返回驶入函数的返回值。faster/faster/urls.pyfromdjango.contribimportadminfromdjango.urlsimportpathfromtestappimportviewsurlpatterns=[path("admin/",admin.site.urls),path('test/',views.test)]faster/testapp/views.pyfromdjango.shortcutsimportHttpResponsedeftest(request):returnHttpResponse('test!')方式二使用include分发路由faster/faster/urls.pyfromdjango.contribimportadminfromdjango.urlsimportpath,includeurlpatterns=[path("admin/",admin.site.urls),# 路由以test开头，那么分发到testapp的urls模块中，namespace用于反向生成urlpath('test/',include('testapp.urls',namespace='test'))]faster/testapp/urls.pyfromdjango.urlsimportpathfrom.importviewsapp_name='test_app'urlpatterns=[path("home/",views.test,name='home'),]faster/testapp/views.pyfromdjango.shortcutsimportHttpResponse,reversedeftest(request):# 如果没有路由分发，反向生成url只需要使用name属性即可# 如果有路由分发，反向生成url需要 'namespace:name' 这种格式url=reverse('test:home')print(url)# 输出 /test/home/returnHttpResponse('test!')1.3.2 路由分发的本质include函数的源码：definclude(arg,namespace=None):app_name=Noneifisinstance(arg,tuple):# Callable returning a namespace hint.try:urlconf_module,app_name=argexceptValueError:ifnamespace:raiseImproperlyConfigured("Cannot override the namespace for a dynamic module that ""provides a namespace.")raiseImproperlyConfigured("Passing a%d-tuple to include() is not supported. Pass a ""2-tuple containing the list of patterns and app_name, and ""provide the namespace argument to include() instead."%len(arg))else:# No namespace hint - use manually provided namespace.urlconf_module=argifisinstance(urlconf_module,str):urlconf_module=import_module(urlconf_module)patterns=getattr(urlconf_module,"urlpatterns",urlconf_module)app_name=getattr(urlconf_module,"app_name",app_name)ifnamespaceandnotapp_name:raiseImproperlyConfigured("Specifying a namespace in include() without providing an app_name ""is not supported. Set the app_name attribute in the included ""module, or pass a 2-tuple containing the list of patterns and ""app_name instead.",)namespace=namespaceorapp_name# Make sure the patterns can be iterated through (without this, some# testcases will break).ifisinstance(patterns,(list,tuple)):forurl_patterninpatterns:pattern=getattr(url_pattern,"pattern",None)ifisinstance(pattern,LocalePrefixPattern):raiseImproperlyConfigured("Using i18n_patterns in an included URLconf is not allowed.")return(urlconf_module,app_name,namespace)整个逻辑很简单，做了一些判断，关键是return，返回了一个含有三个元素的元组，分别是url配置信息的文件路径、应用名称、命名空间路由分发的方式一faster/faster/urls.pyfromdjango.contribimportadminfromdjango.urlsimportpath,includefromtestappimporturlsurlpatterns=[path("admin/",admin.site.urls),#path('test/', include('testapp.urls', namespace='test'))path('test/',(urls,None,None))# urls是python的模块，python中一切皆对象，所以模块也是对象]faster/testapp/urls.pyfromdjango.urlsimportpathfrom.importviewsapp_name='test_app'urlpatterns=[path("home/",views.test,name='home'),]faster/testapp/views.pyfromdjango.shortcutsimportHttpResponse,reversedeftest(request):returnHttpResponse('test!')路由分发的方式二faster/faster/urls.pyfromdjango.contribimportadminfromdjango.urlsimportpath,includefromtestappimportviewsurlpatterns=[path("admin/",admin.site.urls),path('level1/',([path('item1/',([path('content/',views.content1),],None,None)),path('item2/',([path('content/',views.content2),],None,None))],None,None))]faster/testapp/views.pyfromdjango.shortcutsimportHttpResponse,reversedefcontent1(request):returnHttpResponse('content1')defcontent2(request):returnHttpResponse('content2')路由分发结果如下:http://127.0.0.1:5000/level1/-----------------------------------------item1/--------------------------------------------------content/-----------------------------------------item2/--------------------------------------------------content/1.5 自动在app包中查找某个模块并执行1.5.1 python中的包和模块==包==---是一个包含_init_.py文件的文件夹模块---就是一个后缀名为py的文件--testapp# Python中的包--migrations--__init__.py--admin.py# 从这往下都是Python中的模块--apps.py--models.py--tests.py--views.pyPython中一切皆对象，包和模块也是对象。1.5.2 django-admin源码浅析大家在使用django-admin的时候第一步是在每个app的admin.py下面将模型类注册到site中。faster/test_app/apps.pyfromdjango.appsimportAppConfigfromdjango.utils.module_loadingimportautodiscover_modulesclassTestappConfig(AppConfig):default_auto_field="django.db.models.BigAutoField"name="testapp"defready(self):autodiscover_modules('test')faster/test_app/test.pydeffunc():print('我被调用了')func()执行结果：F:\.venvs\py3.10\.venv\Lib\site-packages\django\urls\conf.pychanged,reloading.
我被调用了
WatchingforfilechangeswithStatReloader
Performingsystemchecks...

Systemcheckidentifiednoissues(0silenced).

Youhave18unappliedmigration(s).Yourprojectmaynotworkproperlyuntilyouapplythemigrationsforapp(s):admin,auth,contenttypes,sessions.
Run'python manage.py migrate'toapplythem.
September11,2022-19:22:05
Djangoversion4.1.1,usingsettings'faster.settings'Startingdevelopmentserverathttp://127.0.0.1:8000/
QuittheserverwithCTRL-BREAK.1.6 单例模式方式一：通过包的方式通过利用Python模块导入的特性：在Python中，如果已经导入过的文件再次被重新导入时候，python不会再重新解释一遍，而是选择从内存中直接将原来导入的值拿来用。a.pyclassFoo:def__init__(self,a=1):self.a=afoo=Foo()# foo就是一个单例# 单  一个# 例  对象b.pyimportaprint(a.foo)# <a.Foo object at 0x00000205C1787C40>print(a.foo)# <a.Foo object at 0x00000205C1787C40>方式二：通过重写__new__方法的方式# 实例是通过类创建的，类创建实例要先调用类的__new__方法，然后再执行__init__方法classSingleTon:def__new__(cls,*args,**kwargs):ifnothasattr(cls,'_instance'):cls._instance=super().__new__(cls,*args,**kwargs)returncls._instances1=SingleTon()s2=SingleTon()print(s1)print(s2)1.7 简述元类几乎所有面向对象的语音中，都有类和对象的概念。对象是由类创建出来的，类规范了对象的状态和方法。但是你有考虑过类是由什么创建的吗？类都是由元类创建的，type是所有类的默认元类。继承和实例化是两个概念。同时需要注意以下以下几个特殊方法和内部函数：_new_()  创建一个实例对象_init_() 实例化一个实例对象_call_() 实例() 会执行实例的类的 __call__方法isinstance(obj, cls) obj是不是cls的实例对象issubclass(cls1, cls2) cls1是不是cls2的子类1.8 django中获取app名称和模型类通过模型类的_meta属性获取到模型类所属的app名称和模型名称(小写字母)models.UserInfo._meta.app_label# app名称models.UserInfo._meta.model_name# 数据表名称，模型类转换成小写形式1.9 方法和函数的区别函数defxxx():passprint(type(xxx))#<class 'function'>方法classFoo:deftest(self):passf=Foo()print(type(f.test))# <class 'method'>特殊的函数定义：classFoo:deftest(self):passprint(type(Foo.test))#<class 'function'>如何判断一个对象属于哪个类，类==实例化==得到对象，实例化(创造)关系与继承关系一定要分清楚，否则学不明白面向对象，概念不清晰更别提应用了，面向对象是那么的灵活。所以基础概念一定要牢固fromtypesimportFunctionType,MethodTypedefxxx():passclassFoo:deftest(self):passf=Foo()if__name__=='__main__':print(isinstance(Foo.test,MethodType))# Falseprint(isinstance(xxx,FunctionType))# Trueprint(isinstance(f.test,FunctionType))# False1.10 生成器与yield生成器表达式a=(iforiinrange(100))b=[iforiinrange(100)]print(a)# <generator object <genexpr> at 0x000001D2763004A0>print(type(a))# <class 'generator'>print(type(b))# <class 'list'>importsysprint(sys.getsizeof(a))# 104print(sys.getsizeof(b))# 920从运行结果可以开出，生成器可以大量节省系统内存，并且生成器是特殊的迭代器，可以使用for循环遍历出里面的元素举个例子：小红和小绿都很喜欢吃面包，小红从工厂直接买回来100块，放在家里堆起来，小绿则是饿了的时候去商店买一块，小红就类似与列表，把所有的元素都放到内存中，小绿就类似于生成器，需要的时候才来取。yield实现生成器defxxx():yield1print(xxx())# <generator object xxx at 0x000001F0EC9304A0>print(next(xxx()))# 1生成器还有一些其他用法，如，send、next、throw、yield from、协程等，本组件开发暂时用不到，就不多说了。1.11 反射反射是静态面向对象语言具有的特性，比如Java就严重依赖反射。Python同样具有反射的特性，只要使用内建方法中的getattr(obj, attr)classFoo:# 类变量x=123@classmethoddeff1(cls):print('类方法')@staticmethoddeff2():print('静态方法')deff3(self):print('实例方法')def__init__(self,name='foo'):# 实例变量self.name=namefoo=Foo()getattr(foo,'f1')()getattr(foo,'f2')()getattr(foo,'f3')()print(getattr(Foo,'x'))print(getattr(foo,'name'))print(getattr(foo,'x'))除了getattr之后还有setattrsetattr(obj,attr,value)等价于obj.attr=valuehasattrhasattr(obj,attr)返回TrueorFalsedelattrdelattr(obj,attr)删除obj的attr属性1.12 装饰器语法糖写法importtimedefwrapper(func):print('装饰器执行的时机有点特殊')print(func.__name__)definner(*args,**kwargs):print('start...')start_time=time.time()result=func(*args,**kwargs)print(f'end...total use{time.time()-start_time}s')returnresultinner.__name__=func.__name__returninner@wrapperdeffunc1():time.sleep(2)print('就是玩')@wrapperdeffunc2():time.sleep(1)print('还得玩')func1()print(func1.__name__)func2()print(func2.__name__)关键点1:文件被执行的时候就会被调用。关键点2：装饰器会改变原函数的元信息非语法糖写法wrapper(func1)()# 与语法糖相同1.13 组合查询Q对象1.14 request.GET  对象2 faster组件使用说明首先需要注册app：项目文件夹/settings.pyINSTALLED_APPS=[###'fast',]TEMPLATES=[{"BACKEND":"django.template.backends.django.DjangoTemplates","DIRS":[],"APP_DIRS":True,"OPTIONS":{"context_processors":["django.template.context_processors.debug","django.template.context_processors.request","django.contrib.auth.context_processors.auth","django.contrib.messages.context_processors.messages",],'libraries':{# Adding this section should work around the issue.'staticfiles':'django.templatetags.static',},},},]在你的app中创建一个fast.py模块：--testapp----fast.py所有的配置都将写在fast.py中--testapp​	----models.pyclassUserInfo(models.Model):"""用户模型"""user_name=models.CharField(verbose_name='用户名',max_length=32)password=models.CharField(verbose_name='密码',max_length=32)mobile=models.CharField(verbose_name='手机号',max_length=11)token=models.OneToOneField(verbose_name='token',to='UserToken',on_delete=models.SET_NULL,null=True,blank=True)depart=models.ForeignKey(verbose_name='部门',to='Depart',on_delete=models.SET_NULL,null=True,blank=True)def__str__(self):returnself.user_name2.1 入门示例fast.pyfromfast.service.mainimportsite,FastHandler,get_choice_textfrom.importmodelsfromdjangoimportformsclassHandlerUserInfo(FastHandler):list_display=[FastHandler.display_checkbox,'id','user_name','mobile',FastHandler.display_edit,FastHandler.display_delete]add_model_form_class=UserInfoModelFormhas_add_btn=Trueper_page_count=2order_list=['-user_name']action_list=[FastHandler.action_multi_delete,]search_list=['user_name__contains']site.register(models.UserInfo,HandlerUserInfo).2.2 列表功能-list_display在继承FastHandler的类变量中添加list_diaplay可以定制需要显示的列：除去常规字段，比如’id‘、'user_name'、’mobile‘还可以配置特殊字段：FastHandler.display_checkbox :FastHandler.display_editFastHandler.display_delete2.3 新增按钮-has_add_btn & add_model_form_classhas_add_btn 默认为True , 将其修改为False，界面不具备新增功能。add_model_form_class，新增字段的form表单，可以自定义modelformclassUserInfoModelForm(forms.ModelForm):classMeta:model=models.UserInfofields='__all__'defclean_user_name(self):user_name=self.cleaned_data['user_name']ifuser_name!='kobe':raiseforms.ValidationError('user_name 验证错误')returnuser_name自定义modelform，设置add_model_form_class = 类名即可，本实例中可以写成：add_model_form_class = UserInfoModelForm2.4 按字段排序-order_listorder_list['id', ]  按id升序排['-id',] 按id降序排['id', '-user_name'] 按id升序排，user_name 降序排['c1','c2','c3',......] 按多个字段排2.5 关键词搜索search_list['user_name__contains']  等价于sql中的like['user_name']  需要精准匹配上其他django ORM filter语法2.6 分页per_page_count 必须为整型per_page_count = 1 每页显示1条per_page_count = 3 每页显示3条以此类推。。。。2.7 批量操作action_list = [FastHandler.action_multi_delete, ]目前只支持批量删除