目录html
一对多 多对多 一对一 # 如何判断 换位思考 以图书管理管理系统 图书表 图书和出版社是一对多的外键关系 一对多外键关系 外键字段建在多的那一方
一对一关系创建:author_detail = models.OneToOneField(to='AuthorDetail')前端
ForeignKey字段以及OneToOneField字段 在建立表的时候orm都会自动给该字段加_id的后缀 不管本身有没有加 class Author(models.Model): name = models.CharField(max_length=32) phone = models.BigIntegerField() # 一对一外键关系创建 author_detail = models.OneToOneField(to='AuthorDetail')
多对多关系创建:authors = models.ManyToManyField(to='Author')python
class Book(models.Model): # id是自动建立的 咱们就不写了 title = models.CharField(max_length=64) # price为小数字段 总共8位小数位占2位 price = models.DecimalField(max_digits=8,decimal_places=2) # 书籍与出版社 是一对多外键关系 publish = models.ForeignKey(to='Publish') # 默认关联字段就是出版社表的主键字段 # publish = models.ForeignKey(to=Publish) # to后面也能够直接写表的变量名 可是须要保证该变量名在当前位置的上方出现 # 书籍与做者 是多对多外键关系 authors = models.ManyToManyField(to='Author') # 书籍和做者是多对多关系
一对多关系创建:publish = models.ForeignKey(to='Publish')git
class Book(models.Model): # id是自动建立的 咱们就不写了 title = models.CharField(max_length=64) # price为小数字段 总共8位小数位占2位 price = models.DecimalField(max_digits=8,decimal_places=2) # 书籍与出版社 是一对多外键关系 publish = models.ForeignKey(to='Publish') # 默认关联字段就是出版社表的主键字段 # publish = models.ForeignKey(to=Publish) # to后面也能够直接写表的变量名 可是须要保证该变量名在当前位置的上方出现
路由匹配 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test',views.test), url(r'testadd',views.testadd) ] url方法第一个参数是一个正则表达式 路由匹配按照正则匹配 一旦正则可以匹配到内容 会马上执行对应的视图函数 不会再继续匹配了
用户输入url不加最后的斜杠 django会默认自动加上 你能够在配置文件中指定是否开启该功能 APPEND_SLASH = True/False
无名分组 在路由匹配的时候给某段正则表达式加了括号 匹配的时候会将括号内正则表达式匹配到的内容当作位置参数传递给对应的视图函数 # 无名分组 url(r'^test/([0-9]{4})/',views.test) # 视图函数 def index(request,args): return HttpResponse('')
有名分组 给一段正则表达式起一个别名 匹配的时候会将括号内正则表达式匹配到的内容当作关键字参数传递给对应的视图函数 # 有名分组 url(r'^test/(?P<year>\d+)/',views.test) # 视图函数 def index(request,year): ... 补充: # 无名有名可否混合使用 >>> 不能!!! # url(r'^test/(\d+)/(?P<year>\d+)/', views.test), # 虽然不能混合使用 可是同一种命名方式 可使用多个 # url(r'^test/(\d+)/(\d+)/',views.test), url(r'^test/(?P<xxx>\d+)/(?P<year>\d+)/',views.test),
反向解析
经过一些方法 可以获得一个结果 该结果能够访问到对应的url正则表达式
使用方式 先给路由与视图函数对应关系 起一个名字 url(r'^testadd/',views.testadd,name='add') 前端解析 {% url 'add' %} 后端解析 from django.shortcuts import render,HttpResponse,redirect,reverse reverse('add')
无名分组反向解析django
# 无名分组反向解析 url(r'^testadd/(\d+)/',views.testadd,name='add') 前端解析 {% url 'add' 1 %} 后端解析 reverse('add',args=(12,))
有名分组反向解析json
# 有名分组反向解析 url(r'^testadd/(?P<year>\d+)/',views.testadd,name='add') 前端解析 {% url 'add' 1 %} # 推荐使用 {% url 'add' year= 1 %} # 标准的 后端解析 reverse('add',args=(12,)) reverse('add',kwargs={'year':12})
伪代码诠释 url(r'^edit_user/(\d+)/',views.edit_user,names='edit') 前端: {% for user_obj in user_queryset %} <a href="edit_user/{{ user_obj.id }}/">编辑</a> <a href="{% url 'edit' user_obj.id %}">编辑</a> {% endfor %} 后端: def edit_user(request,edit_id): reverse('edit',args=(edit_id,))
路由分发 当django项目比较庞大的时候 路由与视图函数对应关系较多 总路由代码太多冗长 考虑到总路由代码很差维护 django支持每一个app均可以有本身的urls.py 而且总路由再也不作路由与视图函数的对应关系 而仅仅只作一个分发任务的操做 根据请求的不一样 识别出当前请求须要访问的功能属于哪一个app而后自动 下发到对应app里面的urls.py中 而后由app里面的urls.py作路由与视图函数的匹配 不只如此每一个app除了能够有本身的urls.py以外 还能够有本身的static文件夹 templates模板文件 基于上面的特色 基于django分小组开发 会变得额外的简单 每一个人只须要开发本身的app便可 以后只须要建立一个空的django项目 将多我的的app所有拷贝项目下 配置文件注册 总路由分发一次
须要一个分发的模块 1.总路由 from django.conf.urls import url,include # 简写 url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')) 2.子路由1 from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ] 3.子路由2 from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/',views.index) ]
为了防止多个app路由函数的名字重复,调用的时候就用名称空间。(不推荐)后端
推荐方式:给app路由函数起名字的时候加上前缀app的名字,这样方式路由函数的名字就永远不会重复了app
名称空间(了解) url(r'^app01/',include('app01.urls',namespace='app01')) url(r'^app02/',include('app02.urls',namespace='app02')) 后端解析 reverse('app01:index') reverse('app02:index') 前端解析 {% url 'app01:index' %} {% url 'app02:index' %} # 在给路由与视图函数起别名的时候只须要保证永远不出现冲突的状况便可 # 一般状况下咱们推荐期别名的时候加上当前应用的应用名前缀 推荐: url(r'^index/',views.index,name='app01_index') url(r'^index/',views.index,name='app02_index')
虚拟环境 咱们想作到针对不一样的项目 只安装项目所须要的功能模块 项目用不到的一律不装 来避免加载资源时的消耗 如何建立虚拟环境 虚拟环境就相似于一个纯净的python解释器环境 大白话 没建立一个虚拟幻境就相似于你从新下载一个python解释器 虚拟环境不推荐你使用太多 学习阶段咱们仍是用本机的环境便可 将全部模块所有装到本机环境下
有view的文件就是虚拟环境函数
django版本区别 路由层 1.X用的是url 2.X、3.X用的是path url第一个参数是一个正则表达式 而path第一个参数不支持正则表达式 写什么就匹配什么 若是你以为path很差用 2.x、3.x给你提供了一个跟url同样的功能 re_path 等价于1.x里面的url功能 虽然path不支持正则表达式 可是它给你提供了五种默认的转换器 str,匹配除了路径分隔符(/)以外的非空字符串,这是默认的形式 int,匹配正整数,包含0。 slug,匹配字母、数字以及横杠、下划线组成的字符串。 uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?) 好比:path('login/<int:year>/',login) 除了默认的五种转换器以外 还支持你自定义转换器 class MonthConverter: regex='\d{2}' # 属性名必须为regex def to_python(self, value): return int(value) def to_url(self, value): return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
伪静态 url以.html结尾 给人的感受好像是这个文件是写死的 内容不会轻易的改变 伪静态 为了提升你的网站被搜索引擎收藏的力度 提供网站的SEO查询效率 可是 不管你怎么作优化 都抗不过RMB玩家
视图函数必需要返回一个HttpResponse对象 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求而且返回Web响应。 响应能够是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。 不管视图自己包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此以外没有更多的要求了——能够说“没有什么神奇的地方”。为了将代码放在某处,你们约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。
1.HttpResponse 返回字符串 return HttpResponse('字符串') 2.render 返回html页面 return render(request,'templates文件夹下的html文件名',{'xxx':'hello world'}) 页面上就能够经过{{xxx}}拿到hello world 模板的渲染(将数据在后端按照模板语法放入html对应的位置) 3.redirect 重定向 return redirect(url) # url能够是别人网站的全路径 也能够是本身网站的url后缀 return redirect('/index') return redirect('https://www.mzitu.com')
观察源码可知:
先后端交互的数据格式json
由于前端返回的是一个HttpResponse对象,JsonResponse对象又是HttpResponse对象的子类。 使用方法: 1.导入模块 JsonResponse from django.http import JsonResponse 2.序列化非字典格式数据 kk=[1,2,3,4,5,'你好'] return JsonResponse(kk,safe=False) # 序列化非字典格式数据 须要将safe改成False 3.数据中的汉字不序列化 return JsonResponse(kk,safe=False,json_dumps_params={'ensure_ascii':False})
前端:
<form action="" method="post" enctype="multipart/form-data"> <input type="file" name="myfile"> <input type="submit"> </form>
后端获取:用 FILES
def home(request): if request.method == 'POST': # 获取用户上传的文件数据 print(request.FILES) file_obj = request.FILES.get('myfile') # 文件句柄,前端按钮<input type="file" name="myfile"> print(file_obj.name) # 获取文件名 # 保存 with open(file_obj.name,'wb') as f: for line in file_obj: f.write(line) return render(request,'home.html')