目录html
换位思考,先粘在一张表上面分析, 而后再站在另外一张表上分析前端
外键字段建立在任意一张表均可以,简易在查询频率较高的一方添加python
OneToOneField
正则表达式
models.OneToOneField(to='Author_detail') # fk + unique
外键字段建立在多的那一方django
ForeignKey
后端
models.ForeignKey(to='Publish') # to用来指代跟哪张表有关系 默认关联的就是表的主键字段
外键关系须要建立第三张表来处理。浏览器
ManyToManyField
app
models.ManyToManyField(to='Author') # django orm会自动帮你建立第三张关系表
urlpatterns = [ url(r'^admin/', admin.site.urls), ]
url的第一个参数其实就是一个正则表达式,只要该正则表达式可以匹配到内容,就会马上执行后面的视图函数,再也不往下继续匹配。函数
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其做用就是自动在网址结尾加'/'。post
咱们定义了urls.py:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^blog/$', views.blog), ]
其效果就是:
访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。
若是在settings.py中设置了 APPEND_SLASH=False,此时咱们再请求 http://www.example.com/blog 时就会提示找不到页面。
Django 路由匹配的规律:
?
后面携带的参数将分组内正则表达式匹配到的内容当作位置参数传递给视图函数
url(r'^test/([0-9]{4})/', views.test) 访问的url:http://127.0.0.1/test/1111 # 当你的路由中有分组的正则表达式 那么在匹配到内容 # 执行视图函数的时候 会将分组内正则表达式匹配到的内容当作位置参数传递给视图函数 def test(request,xxx): ''' 此时url有第二个参数,会传递给视图函数位置参数传进来。 若是不写接收的位置参数则会报错 test() takes 1 positional argument but 2 were given ''' print(xxx) # 1111 pass
将分组内正则表达式匹配到的内容当作关键字参数传递给视图函数
url(r'^test/(?P<year>[0-9]{4})/', views.test) 访问的url:http://127.0.0.1/test/1111 # 当你的路由中有分组的正则表达式 那么在匹配到内容 # 执行视图函数的时候 会将分组内正则表达式匹配到的内容当作关键字参数传递给视图函数 def test(request,year): ''' 此时url有第二个参数,会传递给视图函数关键字参数传进来。 若是不写接收的关键字参数则会报错 testadd() got an unexpected keyword argument 'year' ''' print(year) # 1111 pass
利用有名个无名分组 咱们就能够在调用视图函数以前给函数传递额外的参数
注意:无名分组和有名分组不能混合使用
可是同一种分组的状况下 可使用屡次,
无名能够有多个
有名能够有多个
给路由匹配设置一个别名,
根据这个别名,动态解析出一个结果,该结果能够直接访问对应的url。
urls.py: url(r'^home/',views.home,name='hm'), url(r'^index/$',views.index), views.py: def home(request): return HttpResponse(reverse('hm')) def index(request): print(reverse('hm')) # /home/ return render(request,'test.html') test.html: <body> <div>TEST</div> <p><a href="{% url 'hm' %}">点我点我</a></p> </body> 当咱们在浏览器URL输入http://127.0.0.1:8000/index/的时候, python后端进行reverse反向解析成 别名为'hm'的路径前缀,也就是home路径, 用test.html 页面渲染,html也可使用反向解析 python后端使用反向解析: reverse('hm') 前端html使用反向解析: {% url 'hm' %} 将路径解析为/home/。
urls.py: url(r'^home/(\d+)/',views.home,name='hm'), url(r'^index/',views.index), views.py: def home(request,xxx): # 使用无名分组,视图函数必须写位置参数 print(xxx) return HttpResponse('ok') def index(request): print(reverse('hm',args=(1,))) # 无名分组须要手动给别名传递一个参数才能匹配上,这个参数会传递到视图函数当作位置参数。 return render(request,'test.html') test.html: <body> <div>TEST</div> <p><a href="{% url 'hm' 1 %}">点我点我</a></p> </body> 当一个无名分组使用别名的时候,在浏览器URL输入http://127.0.0.1:8000/index/,python后端进行reverse反向解析成 别名为'hm'的路径前缀,也就是home路径,须要手动给解析出来的路径加参数,否则匹配不成功 用test.html 页面渲染,而且html使用反向解析,也须要手动传入参数 python后端使用反向解析: reverse('hm',args=(1,)) 前端html使用反向解析: {% url 'hm' 1 %} 将路径解析为/home/1。
urls.py: url(r'^home/(?P<year>\d+)/',views.home,name='hm'), url(r'^index/',views.index), views.py: def home(request,year): # 使用有名分组,视图函数必须写关键字参数 print(year) return HttpResponse('ok') def index(request): print(reverse('hm',args=(1,))) # 这样也能够,但不正规 print(reverse('hm',kwargs={"year":1})) # 最正规的写法,由于有名分组传入的是关键字参数,用kwargs参数来表示 return render(request,'test.html') test.html: <body> <div>TEST</div> <p><a href="{% url 'hm' 1 %}">点我点我</a></p> # 这样也能够,但不正规 <p><a href="{% url 'hm' year=1 %}">点我点我</a></p> # 最正规的写法,由于有名分组传入的是关键字参数 </body> 当一个无名分组使用别名的时候,在浏览器URL输入http://127.0.0.1:8000/index/,python后端进行reverse反向解析成 别名为'hm'的路径前缀,也就是home路径,须要手动给解析出来的路径加参数,否则匹配不成功。 用test.html 页面渲染,而且html使用反向解析,也须要手动传入参数 python后端使用反向解析: reverse('hm',kwargs={"year":1}) 前端html使用反向解析: {% url 'hm' year=1 %} 将路径解析为/home/1。
伪代码以编辑用户信息为例,演示具体用法:
urls.py: url(r'^edit_user/(\d+)',views.edit_user,name='edit'), views.py: def edit_user(request,edit_id): # 查出来全部 user_list # edit_id 就是用户想要编辑数据的主键值 print(edit_id) return render(request,'edit_user.html',{"user_list":user_list}) edit_user.hmtl: {% for user_obj in user_list %} <a href="/edit_user/{{ user_obj.id }}">编辑</a> <a href="{% url 'edit' user_obj.id %}">编辑</a> {% endfor %}
前言,在django中全部的app均可以有本身的独立的urls.py、templates、static文件夹
那么正是因为这个特色,你的django项目能够由多我的一块儿开发。小组长最后只须要把全部的开发的app整合到一个空的django项目里面,在settings配置文件里注册就能够了。
路由分发解决的就是项目的总路由匹配关系过多的状况,使用路由分发 会将总路由再也不作匹配的活 而仅仅是作任务分发
咱们新建一个app02,如今个人目录结构是:
python3 manage.py startapp app02
好了以后
咱们在app01目录中建立urs.py app01/urls.py: from app01 import views from django.conf.urls import url urlpatterns = [ url(r'^reg/',views.reg), ] app01/views.py: def reg(request): return HttpResponse("app01 reg") ----------------------------------- app02/urls.py: from app02 import views from django.conf.urls import url urlpatterns = [ url(r'^reg/',views.reg), ] app02/views.py: def reg(request): return HttpResponse("app02 reg") 总urls:mysite/urls.py: from app01 import urls as app01_urls from app02 import urls as app02_urls urlpatterns = [ url(r'^app01/',include(app01_urls)), url(r'^app02/',include(app02_urls)), ] 或者更省事的写法,不用把两个app的urls.py导过来: urlpatterns = [ url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')), ] 最终效果,在浏览器url中输入 http://127.0.0.1:8000/app01/reg # app01 reg http://127.0.0.1:8000/app02/reg # app02 reg
当多个app中出现了起别名冲突的状况 你在作路由分发的时候 能够给每个app建立一个名称空间,而后在反向解析的时候 能够选择到底去哪一个名称空间中查找别名
url(r'^app01/',include('app01.urls',namespace='app01')), url(r'^app02/',include('app02.urls',namespace='app02')) # 后端 print(reverse('app01:reg')) print(reverse('app02:reg')) # 前端 <a href="{% url 'app01:reg' %}"></a> <a href="{% url 'app02:reg' %}"></a> 其实不用这么麻烦, 参考建议 起别名的时候统一加上应用名前缀,这样你的别名就不会重复了。 urlpatterns = [url(r'^reg/',views.reg,name='app01_reg')] urlpatterns = [url(r'^reg/',views.reg,name='app02_reg')]
将一个动态网页假装成一个静态的网页,来提升搜索引擎SEO的查询频率,提升网站的曝光度!
怎么作呢,好比博客园是一个动态网站,可是看起来像一个静态网站,是由于每篇文章都有后缀名.html
那么咱们也能够写,在路由匹配规则中写上
# https://www.cnblogs.com/qinyujie/p/11394671.html url(r'^article/(\d+).html',views.article)
虚拟环境就至关于从新下载了一个纯净的python解释器,以后项目用这个虚拟环境,你须要什么就安装什么,与系统环境上存在的软件不冲突。
urls.py路由匹配的方法有区别。
导入的模块是
from django.conf.urls import url
,
urlpatterns 中 url 对应的是正则表达式,
以下:
from django.conf.urls import url urlpatterns = [ url = ('test',view.test) ]
导入的模块是from django.urls import re_path,path
path中第一个参数不支持正则表达式,写了什么就只能匹配什么,匹配不到就报错。
django 2.X 以为你习惯了以前的正则表达式来匹配,特别人性化 ,
提供一个re_path
方法,这个方法就是1.X版本中的url()
以下:
from django.urls import path,re_path urlpatterns = [ path = ('test',view.test), re_path = (r'^test/(\d+)',view.test) ]
django 2.X的版本中还提供了五种转换器,
urlpatterns = [ path = ('test/<str:\d+>',view.test) path = ('test/<int:\d+>',view.test) path = ('test/<slug:\d+>',view.test) path = ('test/<uuid:\d+>',view.test) path = ('test/<path:\d+>',view.test) ]
除了内置的五种转换器外,还能够自定义本身的转换器。
class CVT185Phone: regex = '185\d{8}' def to_python(self, value): return int(value) def to_url(self, value): return '%11d' % value from django.urls import register_converter from app.converter import CVT185phone register_converter(CVT185phone,'phone185') path('page/<phone185:msg>/',views.page,name="pages")
经过路由分发,使用app01上传文件的功能上传一个文件;
mysite/urls.py urlpatterns = [ url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')), ] app01/urls.py from app01 import views from django.conf.urls import url urlpatterns = [ url(r'^upload/',views.upload,name='app01_upload'), ] app01/views.py from django.shortcuts import reverse,render,HttpResponse,redirect def upload(request): if request.method == "POST": print(request.FILES) file_obj = request.FILES.get("myfile") with open(file_obj.name,"wb") as f: for i in file_obj: f.write(i) return render(request,'upload.html') templates/upload.html <body> <form action="" method="post" enctype="multipart/form-data"> 请选择文件 <input type="file" name="myfile"> <input type="submit" class="btn btn-primary">提交 </form>