知了超细讲解Django打造大型企业官网学习记录
02diango url 笔记
#第一个项目笔记:
##创建项目:
1.通过命令行的形式:
首先要进入到安装了django的虚拟环境中,然后执行命令:
django-admin startproject [项目的名称]
这样就可以在当前目录下创建一个项目了。
2.通过pycharm的方式:
文件>新建项目>选择django,然后指定项目所在的路径,以及python解释器,再点击Create就可以创建项目了。
##运行项目:
1.终端:
进入项目文件夹中,然后进行以下命令即可运行:
python manage.py runserver
2.pycharm:
直接点击右上角的绿色三角箭头按钮就可以了。
注意:用pycharm运行项目,要避免一个项目运行多次。
在项目配置中,把“只用单一实例”那个选项勾选上,避免以上的问题。
##改变端口号:
1.在终端:
运行的时候加上一个端口号就可以了。命令为'python manage.py runserver 9000'
2.在pycharm中:
右上角->项目配置->port,改成你想要的端口号,重新运行。
##项目结构分析:
1.'manage.py'上都是基于这个文件。一般都是在终端输入 python manage.py [子命令],可以输入 python manage.py help 看下能做什么事情,除非你知道自己在做什么,一般情况下不应该编辑这个文件。
2.'settings.py' 保存项目所有的配置信息。
3.'wsig.py':专门用来做部署的,不需要修改。
##django推荐的项目规范:
按照功能或者模块进行分层,分成一个个app,所有和某个模块相关的视图层都写在对应的app的views.py中,并且模型和其他的也是类似。然后django已经提供了一个比较方便创建app的命令叫做 'python manage.py startapp [app的名称]'。把所有的代码都写在各自的app中。
##DEBUG模式:
如果开启了DEBUG模式,那么以后我们修改了django项目的代码,然后按下ctrl+s,那么django就会自动给我们重启项目,不需要手动重启。
2.如果开启了DEBUG模式,那么以后django项目中的代码出现bug了,那么在浏览器中和控制台会打印出错信息。
3.在生产环境中,禁止开启DEBUG模式,不然会有很大的安全隐患。
4.如果将DEBUG模式设置为False,那么必须要设置ALLOWED_HOSTS。
##ALLOWED_HOSTS:
这个变量是用来设置以后别人只能通过这个变量中的ip地址或者域名来访问。
#视图函数:
1.视图函数的第一个参数必须是request,这个参数绝对不能少。
2.视图函数的返回值必须是'django.httpresponse.HttpResponse8ase'的子类的对象。
#url传递参数:
##url映射
1.为什么会去urls.py文件中寻找映射呢?
是因为在'settings.py'文件中配置了'ROOT_URLCONF'为'urls.py',所有django会去'urls.py'中寻找。
2.在'urls.py'中我们所有的映射,都应该放在'urlpatterns'这个变量中。
3.所有的映射不是随便写的,而是使用'path'函数或者是're_path'函数进行包装的。
##url传参数
1.采用在url中使用变量的方式:
在path的第一个参数中,使用'<参数名>'的方式可以传递参数。然后在视图函数中也要写一个参数,视图函数中的参数必须和url中的参数名称保持一致,不然就找不到这个参数。另外,url中可以传递多个参数。
2.采用查询字符串的方式:
在url中,不需要单独的匹配查询字符串的部分,只需要在视图函数中使用'request.GET.get('参数名称')'的方式来获取,示例代码如下:
def author_detail(request): author_id=request.GET.get['id'] text='作者的id是:%s'% author_id return HttpResponse(text)
因为查询字符串使用的是'GET'的请求,所以我们通过'request.GET'来获取参数,并且因为'GET'是一个类似于字典的数据类型,所有获取值跟字典的方式都是一样的。
##url参数转换器:
1.str:除了斜杠'/'以外所有字符都是可以的。
2.int:只有是一个或者多个的阿拉伯数字。
3.path:所有的字符都是满足的。
4.uuid:只有满足'uuid.uuid4()'这个函数返回的字符串格式。
5.slug:英文中的横杠或者英文字符或者阿拉伯数字或者下划线采满足。
#urls模块化
如果项目变得越来越大,那么url就会变得越来越多,如果都放在主'urls.py'文件中,那么将不太好管理。因此我们可以将每个app自己的urls放到自己的app进行管理。一般我们会在app中新建一个urls.py文件用来存储所有和这个app相关的子url。
需要注意的地方:
1.应该使用'include'函数包含'urls.py',并且这个'urls.py'的路径是相对于项目的路径。示例代码如下:
urlpatterns=[ path('admin',admin.site.urls), path('book',include('book.urls')) ]
2.在'app'的'urls.py'中,所有的url匹配也要放在一个叫做'urlpatterns'的变量中,否则找不到。
3.'url'是会根据主'urls.py'和app中的'urls.py'进行拼接的,因此需要注意不要多加斜杠。
#url命令
##为什么需要url命名?
因为url是经常变化的。如果在代码中写死可能会经常改代码,给url取个名字,以后使用url的时候就使用它的名字进行反转就可以了,就不需要写死url了。
##如何给一个url指定名称?
在'path'函数中,传递一个'name'参数就可以指定。示例代码如下:
urlpatterns=[ path('',views.index,name='index'), path('login/',views.login,name='login') ]
##应用命名空间:
在多个app之间,有可能产生同名的url,这时候为了避免反转url的时候产生混淆,可以使用应用命名空间,来做区分。定义应用命名空间非常简单,只要在'app'的'urls.py'中定义一个叫做'app_name'的变量。
##应用(app)命名空间和实例命名空间:
一个app,可以创建多个实例,可以使用多个url映射同一个app,所以就会产生一个问题。以后做反转的时候,如果使用命名空间,那么就会发生混淆。为了避免孩子也给问题,我们可以使用实例命名空间。实例命令空间也是非常简单,只要在'include'函数中传递一个'namespace'变量即可。实例代码如下:
urlpatterns=[ path(,include('front.urls')), #同一个app夏有两个实例 path('cms1/',include('cms.urls',namespace='cms1')), path('cms2/',include('cms.urls',namespace='cms2')), ]
以后在做反转的时候,就可以根据实例命名空间来指定具体的url,示例代码如下:
def index(request): username=request.GET.get('username') if username: return HttpResponse('cms首页') else: #获取当前命名空间 current_namespace=request.resolver_math.namespace return redirect(reverse('%s:login' % current_namespace))
#include函数的用法:
1.include(module,namespace=None):
*module:子url的模块字符集。
*namespace:实例命名空间。这个地方需要注意一点。如果指定实例命名空间,那么前提必须要先指定应用命名空间,也就是在子'urls.py'中添加'app_name'变量。
2.include((pattern_list,app_namespace),namespace=None):'include'函数的第一个参数既可以为一个字符串,也可以为一个元组,如果是元组,那么元组的第一个参数是子'urls.py'模块的字符串,元组的第二个参数是应用命名空间。也就是说,应用命名空间既可以在子'urls.py'中通过'app_name'指定,也可以在'include'函数中指定。
3.include(pattern_list): 'pattern_list'是一个列表,这个列表中装的是'path'或者're_path'函数,实例代码如下:
path('movie/',include([ path('',views.movie), path('list/',views.movie_list), ]))
#re_path笔记
1.re_path和path的作用都是一样的,只不过're_path'是在写url的时候可以用正则表达式,功能更加强大。
2.写正则表达式都推荐使用原生字符串,也就是以'r'开头的字符串。
3.在正则表达式中定义变量,需要使用圆括号括起来。在这个参数是有名字的,那么需要使用'?p<参数的名字>',然后在后面添加正则表达式的规则,示例代码如下:
from dajango.urls import re_path from . import views urlpatterns=[ #r'' 代表的是原生字符串(raw) re_path(r'^$',view.article), re_path(r'^list/(?p<year>\d{4})/$,views.article_list'), re_path(r'^list/(?p<month>\d{2})/$',views.article_list_month) ]
4.如果不是特别要求,直接使用'path'就够了,省的把代码搞得很麻烦(因为正则表达式其实是非常隐晦的,特别是一些比较复杂的正则表达式,今天写的明天可能就不记得了),除非是url中确实是需要使用正则表达式来解决才使用're_path'。
#reverse笔记:
1.如果在反转url的时候,需要添加参数,那么可以传递'kwargs'参数到'revers'函数中。示例代码如下:
detail_url=reverse('detail',kwargs={'article_id':1,'page'=2})
2.如果想要添加查询字符串的参数,则必须手动的进行拼接。示例代码如下:
login_url=reverse('login')+'?next=/'
#自定义url(PATH)转换器笔记:
##需求:
实现一个获取文章列表的demo,用户可以根据'/article/文章分类/'的方式来获取文章。其中文章分类采用的是'分类1+分类2+分类3...'的方式拼接的,并且如果只有一个分类,那就不需要加号。示例如下:
#1.第一种:获取python分类下的文章 /article/python/ #2.第二种:获取python和django分类下的文章 /article/python+django/ #3.第三种:获取python和django和flask分类下的文章 /article/python+django+flask/ 以此类推...
在“文章分类”参数传到视图函数之前要把核心分类分开存储到列表中。
比如参数是'python+django',那么传到视图函数的时候变成'['python','django']'
以后在使用reverse反转的时候,限制传递“文章分类”的参数应该是一个列表,并且将这个列表变成'python+django'的形式。
##自定义url转换器
之前已经学到过一些django内置的url转换器,包含有int、uuid等,有时候这些内置的url转换器并不能满足我们的需求,因此django给我们提供了一个借口可以让我们自己定义自己的url转换器。
自定义url转换器按照以下五个步骤来走就可以了:
1.定义一个类,直接继承自object就可以了。
2.在类中定义一个熟悉regex,这个属性是用来限制url转换器规则的正则表达式。
3.实现 to_python(self,value) 方法,这个方法是将url中的值转换以下,传递给视图函数的。
4.实现 to_url(self,value) 方法,这个方法是在做url反转的时候,将传进来的参数转换后拼接成一个正确的url。
5.将定义好的转换器,使用'django.urls.converters.register_converter'注册到django中。
示例代码如下:
from django.urls import register_converter class CategoryConverter(object): regex=r'\w+|(\w+\+\w+)+' def to_python(self,value): #python+django+flask #['python','django','flask'] result=value.spilt('+') return result def to_url(self,value): #value:['python','django','flask'] #python+django+flask if isinstance(value,list): result='+'.join(value) return result else: raise RuntimeError('转换url的时候,分类参数必须为列表1') register_converter(CategoryConverter,'cate')
#url映射的时候指定默认参数:
使用path或者是re_path后,在route中都可以包含参数,而有时候想指定默认的参数,这时候可以通过以下方式来完成。示例代码如下:
from django.urls import path from . import views urlpatterns=[ path('bolg/',views.page), path('blog/page<int:num>/',views.page), ] #View(in blog/views.py) def page(request,num=1): #Output the appropriate page of blog entries,according to num.
当在访问blog/的时候,因为没有穿递num参数,所以会匹配到一个url,这时候就执行view.page这个视图函数,而在page函数中,又有num=1这个默认参数。因此这时候就可以不用穿递参数。而如果访问blog/1的时候,因为在穿递参数的时候穿递了num,因此会匹配到第二个url,这时候也会执行view.page,然后把穿递进来的参数传给page函数中的num。
来源:知了超细讲解Django打造大型企业官网