1.数据库迁移命令
python3 manage.py makemirgatiops
python3 manage.py mirgate
只要你修改了models.py中跟数据库相关的代码 就必须重新执行上述的两条命令
2.models
CharField必须要指定max_length参数 不指定会直接报错
verbose_name该参数是所有字段都有的 就是用来对字段的解释
orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段
数据的增删改查:
查:res = models.User.objects.filter(username=username)
返回值你先看成是列表套数据对象的格式
它也支持索引取值 切片操作 但是不支持负数索引
增:res = models.User.objects.create(username=username,password=password)
第二种增加
user_obj = models.User(username=username,password=password)
user_obj.save() # 保存数据
3.request
# form表单action三个参数写法
request.method # 获取当前请求方式 全大写的字符串
request.GET # 获取url问好后面携带的参数
.get() 列表最后一个元素
.getlist() 拿整个列表
request.POST # 获取post请求提交过来的普通键值对(不包含文件)
.get() 列表最后一个元素
.getlist() 拿整个列表
4.配置MySQL
(1)配置文件中配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day60', 'USER':'root', 'PASSWORD':'admin123', 'HOST':'127.0.0.1', 'PORT':3306, 'CHARSET':'utf8' } }
(2).init文件指定pymysql
import pymysql pymysql.install_as_MySQLdb()
5.数据的查、改、删
(1)查
user_queryset = models.User.objects.all() return render(request,'userlist.html',locals())
(2)编辑
点击编辑按钮朝后端发送编辑数据的请求
如何告诉后端用户想要编辑哪条数据?
将编辑按钮所在的那一行数据的主键值发送给后端
利用url问号后面携带参数的方式
{% for user_obj in user_queryset %} <tr> <td>{{ user_obj.id }}</td> <td>{{ user_obj.username }}</td> <td>{{ user_obj.password }}</td> <td> <a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a> <a href="" class="btn btn-danger btn-xs">删除</a> </td> </tr> {% endfor %}
后端查询出用户想要编辑的数据对象 展示到前端页面供用户查看和编辑
def edit_user(request): # 获取url问号后面的参数 edit_id = request.GET.get('user_id') # 查询当前用户想要编辑的数据对象 edit_obj = models.User.objects.filter(id=edit_id).first() if request.method == "POST": username = request.POST.get('username') password = request.POST.get('password') edit_obj.username = username edit_obj.password= password edit_obj.save() return redirect('/userlist/') return render(request,'edit_user.html',locals())
批量更新
models.User.objects.filter(id=edit_id).update(**kwargs)
单个更新
user_obj = models.User.objects.filter(id=edit_id).first() user_obj.username = 'jason' user_obj.passsword = '666' user_obj.save()
(3)删除
def delete_user(request): delete_id = request.GET.get('user_id') models.User.objects.filter(id=delete_id).delete() return redirect('/userlist/')
6.django orm创建表关系
创建表关系 先将基表创建出来 然后再添加外键字段
class Book(models.Model): title = models.CharField(max_length=32) # 总共八位 小数点后面占两位 price = models.DecimalField(max_digits=8,decimal_places=2) # 默认就是与出版社表的主键字段做外键关联 publish = models.ForeignKey(to='Publish') # 图书和作者是多对多的关系 外键字段建在任意一方均可 但是推荐你建在查询频率较高的一方 authors = models.ManyToManyField(to='Author') class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # 作者与作者详情是一对一的关系 外键字段建在任意一方都可以 但是推荐你建在查询频率较高的表中 author_detail = models.OneToOneField(to='AuthorDetail') class AuthorDetail(models.Model): phone = models.BigIntegerField() # 或者直接字符类型 addr = models.CharField(max_length=32)
7.django请求生命周期流程图
浏览器
发送请求(HTTP协议)
web服务网关接口
1.请求来的时候解析封装
响应走的时候打包处理
2.django默认的wsgiref模块不能承受高并发 最大只有1000左右
上线之后会替换成uwsgi来增加并发量
3.WSGI跟wsgiref和uwsgi是什么关系
WSGI是协议
wsgiref和uwsgi是实现该协议的功能模块
django后端
1.django中间件
类似于django的保安 门户
2.urls.py 路由层
识别路由匹配对应的视图函数
3.views.py 视图层
网站整体的业务逻辑
4.templates文件夹模版层
网站所有的html文件
5.models.py模型层
ORM
8.路由层
(1)路由匹配
urlpatterns = [ url(r'^admin/', admin.site.urls), # 首页 url(r'^$',views.home), # 路由匹配 url(r'^test/$',views.test), url(r'^testadd/$',views.testadd), # 尾页(了解) url(r'',views.error), ]
(2)无名分组
分组:就是给某一段正则表达式用小括号扩起来
url(r'^test/(\d+)/',views.test) def test(request,xx): print(xx) return HttpResponse('test')
无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
(3)有名分组
url(r'^testadd/(?P<year>\d+)',views.testadd) def testadd(request,year): print(year) return HttpResponse('testadd')
有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数
(4)反向解析
先给路由与视图函数起一个别名
url(r'^func_kkk/',views.func,name='ooo')
后端反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse reverse('ooo')
前端反向解析
<a href="{% url 'ooo' %}">111</a>
9.form表单上传文件
form表单上传文件类型的数据
1.method必须指定成post
2.enctype必须换成formdata
def ab_file(request): if request.method == 'POST': # print(request.POST) # 只能获取普通的简直对数据 文件不行 print(request.FILES) # 获取文件数据 # <MultiValueDict: {'file': [<InMemoryUploadedFile: u=1288812541,1979816195&fm=26&gp=0.jpg (image/jpeg)>]}> file_obj = request.FILES.get('file') # 文件对象 print(file_obj.name) with open(file_obj.name,'wb') as f: for line in file_obj.chunks(): # 推荐加上chunks方法 其实跟不加是一样的都是一行行的读取 f.write(line) return render(request,'form.html')
10.CBV
视图函数既可以是函数也可以是类
只要是处理业务逻辑的视图函数 形参里面肯定要有request
url(r'^login/',views.MyLogin.as_view())
from django.views import View class MyLogin(View): def get(self,request): return render(request,'form.html') def post(self,request): return HttpResponse('post方法')
函数名/方法名 加括号执行优先级最高
11.模块语法传值
(1)标签
# for循环 {% for foo in l %} <p>{{ forloop }}</p> <p>{{ foo }}</p> 一个个元素 {% endfor %} {'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False} # if判断 {% if b %} <p>baby</p> {% elif s%} <p>都来把</p> {% else %} <p>老baby</p> {% endif %} # for与if混合使用 {% for foo in lll %} {% if forloop.first %} <p>这是我的第一次</p> {% elif forloop.last %} <p>这是最后一次啊</p> {% else %} <p>{{ foo }}</p> {% endif %} {% empty %} <p>for循环的可迭代对象内部没有元素 根本没法循环</p> {% endfor %} # 处理字典其他方法 {% for foo in d.keys %} <p>{{ foo }}</p> {% endfor %} {% for foo in d.values %} <p>{{ foo }}</p> {% endfor %} {% for foo in d.items %} <p>{{ foo }}</p> {% endfor %} # with起别名 {% with d.hobby.3.info as nb %} <p>{{ nb }}</p> 在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式 <p>{{ d.hobby.3.info }}</p> {% endwith %}
(2)自定义过滤器、标签、inclusion_tag
""" 先三步走 1.在应用下创建一个名字”必须“叫templatetags文件夹 2.在该文件夹内创建“任意”名称的py文件 eg:mytag.py 3.在该py文件内"必须"先书写下面两句话(单词一个都不能错) from django import template register = template.Library() """ # 自定义过滤器 @register.filter(name='baby') def my_sum(v1, v2): return v1 + v2 # 使用 {% load mytag %} <p>{{ n|baby:666 }}</p> # 自定义标签(参数可以有多个) 类似于自定义函数 @register.simple_tag(name='plus') def index(a,b,c,d): return '%s-%s-%s-%s'%(a,b,c,d) # 使用 标签多个参数彼此之间空格隔开 <p>{% plus 'jason' 123 123 123 %}</p> # 自定义inclusion_tag """ 内部原理 先定义一个方法 在页面上调用该方法 并且可以传值 该方法会生成一些数据然后传递给一个html页面 之后将渲染好的结果放到调用的位置 """ @register.inclusion_tag('left_menu.html') def left(n): data = ['第{}项'.format(i) for i in range(n)] # 第一种 # return {'data':data} # 将data传递给left_menu.html # 第二种 return locals() # 将data传递给left_menu.html {% left 5 %} # 总结:当html页面某一个地方的页面需要传参数才能够动态的渲染出来,并且在多个页面上都需要使用到该局部 那么就考虑将该局部页面做成inclusion_tag形式
12.模板的继承
{% extends 'home.html' %}
# 继承了之后子页面跟模版页面长的是一模一样的 你需要在模版页面上提前划定可以被修改的区域
{% block content %}
模版内容
{% endblock %}
# 子页面就可以声明想要修改哪块划定了的区域
{% block content %}
子页面内容
{% endblock %}
# 一般情况下模版页面上应该至少有三块可以被修改的区域
1.css区域
2.html区域
3.js区域
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
# 每一个子页面就都可以有自己独有的css代码 html代码 js代码
13.模板的导入
{% include 'wasai.html' %}