今天学习了orm模型中的表关系处理也就是多对一,和一对多 最主要就是理解,理解了就是很简单的东西了, 其中一对多的话就好比如,一本图书 1.天龙八部,图书有名称和出版日期, 2.图书里面有非常多的英雄人物,这里可以代表表关系中的多, 英雄人物有英雄个性,人物身高,属性,特点,性别,技能等等, *** 天龙八部是1,而英雄人物是多,所以是一对多的关系, 我的理解是这样的, 关于外键关联的话就是在models中定义的时候加上你需要的外键关联字段比如 book_key=models.ForeignKey(‘books’,on_delete=models.CASCADE) 这样就引用了books的表的id来关联到英雄的表中, 他的命名规则是 字段名book_key_id后面接上id 这样就在英雄表中生成了外键约束关系, *** 查询部分 *** 在关系1,也就是图书表books中,需要先增加一条新建一条记录 *** a=books() a.name=’天龙八部’ a.time=’2020-03-17′ *** 添加了记录之后就表示有了一本图书了 有了图书之后我们还可以增加英雄 *** h=HreoInfo() h.name=’段誉’ h.gender=’男’ h.age=’18’ h.comment=’吹牛皮’ h.id_key # 外键字段,暂时留空 h.save() # 保存 *** 接着就是最最主要的外键关联部分了 *** 首先获取到图书的id # 必须要的因为关联是通过图书的id进行外键关联的, *** book_id=books.objects.get(id=1) # 拿到了id *** 接着进行关联 首先拿到段誉的数据 *** d=HeroInfo.objects.get(name=’段誉’) *** 拿到了段誉的值给到一个对象里面存着, 然后把段誉的id_key字段设置成刚才拿到的book_id *** d.id_key=book_id # 需要注意是外键一定是一个对象,也就是不能自己手动设置,手动设置的话会直接应发一个错误的 d.save() 保存就好了, *** 今天的笔记就先到这里啦,弄清楚了表关系的处理就好办啦2020-3-17 *** 如果要从1对多关系表中的1表中取到多关系表中的数据,可以这样取 *** 先定义1表的对象, *** 取值的时候一定要先找到数据行,不然谁知道你要取谁的值呢? a=Author.objects.get(id) 然后用1表的对象.上多表的表名 a.content_set.all(),这样就可以取到引用了1的id的所有2表中的数据了, *** 从多表中查看1表中的数据可以这样做 获取多表中的数据id,然后拿着id直接.上外键然后接着1表中的字段名就可以拿到1表中的信息了 例如1表author ,多表 content,外键外author_id 首先 c=content.objects.get(id=1) c.author.name # 拿着多表中的id直接取1表中的值即可 *** 接着在admin中添加管理数据表页面的话可以这样做 先导入modwls的模型表 如果要自己定义管理页面的表显示形式的话可以这样写 你需要重新写一个类 *** class Aadmin(admin.ModelAdmin): list_display=[‘id’,’name’,’title’] *** 然后在注册页面引入类名即可 from app名字.models import 类名(表名) admin.site.register(导入的表名,自定义的管理样式类名) admin.site.register(Author,Aadmin) *** 然后在刷新管理页面就可以看到新的效果了 这样就算注册好了,就可以在admin页面中操作你注册的数据表了 *** 简单的案例,用orm模型从数据库取出数据,然后展示到前台模板上, 1.首先定义book的url 2.定义每一本图书的详情页url 3.book页面展示所有的图书 4.点击展示的图书后可以进入到每一本图书的详情页面,详情页面有图书的详细信息 5.开始实现 *** 1.其实实现起来还是蛮简单的,先定义两个视图函数, 一个是books展示页,还有一个是图书的详情页detail, 2.接着定义url,两个url 一个是books的url还有一个是books/<bid>图书详情页的url,因为详情页是动态的,所以用变量bid来表示,接着回到视图页面中 3.views中,先写books图书展示页, 注意哦,先导入models里面的模型, from . import models, 接着通过orm模型从数据库中取出数据然后render给前台模板,总体代码是这样的 *** # 显示图书信息 def show_books(request): ”’显示图书信息”’ # 通过models查找图书表中的数据 books = models.Content.objects.all() return render(request,’show_books.html’,context={‘books’:books}) *** 然后在定义图书详情页的视图 *** def detail(request,bid): ”’查询图书关联的作者信息”’ # 根据bid查询图书作者 book=models.Content.objects.get(id=bid) author=book.author.name author1=book.author.sex return render(request,’detail.html’,context={‘book’:book,’author’:author}) 因为urls中定义了一个变量bid,所以在定义视图函数的时候记得把bid引用进来,接着就是一句orm的查询语句,通过get拿到bid的值,bid也就是每一本数的id值,然后把查询到的值给到变量book 通过变量book然后在通过外键,获取到作者的名字,把获取到的值给到变量author,这里就完成了数据的提取,接着就是用render返回给前台模板渲染了, *** 前台模板部分 *** 前台部分的话就直接通过jinja2模板语言直接提取就好啦,图书页可以用for循环提取所有数据 *** {% for book in books %} <li><a href=”{{ book.id }}”>{{ book.title }}</a></li> {% endfor %} *** 详情页的话就更简单了,直接提取content传递的键就好了 *** <h1>{{ book.title }}</h1> {{ author }}<br> 主要内容:{{ book.content }} *** 接着加一点功能,增加和删除,其实理解了也是非常简单的,原理就是通过每一本图书的id来进行图书删除, 比如,要删除id为1的图书,就直接定义一个delete视图, *** url视图是这样的 *** path(‘books/delete/<bid>’,views.delete,name=’delete’), *** 仔细观察可以看到有个变量bid,请求到的bid是用来传递图书id的, *** 传递图书id可以在html中这样写 *** <a href=”{% url ‘book_author:delete’ bid=book.id %}”>删除</a> 通过url翻转来获取到删除图书的url,url后面接着的参数就是图书的id,实现动态的删除, *** 视图函数这样写 *** def delete(request,bid): de=models.Content.objects.get(id=bid) de.delete() return HttpResponseRedirect(‘/book/books’) 通过捕捉到bid来进数据库进行删除 *** 需要注意html页面中url href地址,一般推荐用URL 动态的来写,如果一定要用到静态写法(写死),那么一定要注意,开头一定要以/开头,不然url会寻址错误的 *** orm模型选项, auto_now_add=True 创建时间 开启了为真的时候会自动的创建当前时间 auto_now=True 更新时间 开启了为真的时候会更新为当前的时间 primary_key 主键 unique 唯一约束 db_index 创建约束 db_column 字段名称,如果未指定就用属性的名称 null 是否允许为空,默认为False blank 默认为False,是否允许空白字符 给后管理页面用的, get 返回表中的一条数据,只返回一条 如果查询到没有数据将返回DoesNotExist 异常,如果查询到多条的话也抛出一个异常 all 返回表中的所有数据 filter 返回满足条件的数据 返回一个Queryset对象 exclude 返回不满足条件的数据 返回一个Queryset对象 order_by 排序 和.all配合使用,可以用多个字段进行排序,order_by(‘id’,’title’)默认是升序,如果字段前加-号就是降序排序,从大到小,.all可以省略 Q 表达式,暂时用作 或 逻辑 or 前面加-表示取反 与或非 F 表达式 类属性之间进行比较 聚合函数,sum count max min avg Books.objects.aggregate(Count(‘id’)) 我要统计id数量,直接用aggregate 然后写上相应的属性名字即可, 不能用* 否则会抛出typrerror 比如我要计算所有id的总和 Books.objects.aggregate(Sum(‘id’)) 这样就聚合了Books.objects.aggregate(Avg(‘id’)) 这是求平均值,返回数据类型是一个字典,{id__sum:750} 键是字段属性名字加上使用的聚合函数类型,值就是直接返回聚合后的结果 *** 查询集是惰性查询,只有使用到数据库的数据的时候才会和数据库进行交互查询 queryset会缓存数据,第一次查询后会从数据库里拿,第二次查询会直接从查询集中取出来 对一个查询集切片操作的时候会产生一个新的查询集,和原来的查询集没有关系了,查询集切片下标不允许为负数 *** 多对多关系 例子: 新闻类-新闻类型类- 体育新闻 国际新闻 用models.ManyToManyFleld() 随便在哪边定义都可以 一对一关系 例子:员工基本信息类-员工详细信息类-员工工号 models.OneToOneField() 随便在哪边定义都可以 一对多关系 例子:班级-学生,一个班级,多个学生 models.OneToManyField() 必须在多地属性表那边定义,也就是关系必须定义在学生表中,学生记住班级容易寻找,不可能班级表去记录学生人数的 *** 自关联,特殊的一对多 暂时懵的 *** 管理器对象 自定义一个manage管理器对象 book=models.Manager() # 这样就自定义了类对象了 查询的会后就通过Book.book.all() 来查询。 这样定义什么用了没有 正确做法是这样的 class styleManager(models.Manager) 然后在下面直接调用这个类就好了 objects=styleManager() 然后就可以去查询了 应用场景, 1.改变查询结果集 2.添加额外的方法 就是自定义objects查询管理器对象,高级操作。。。 *** 如果在调试过程中出现了404错误, 1.首先检查url有没配置好 2.url配置是否有误 如果出现了500错误,就是服务器内部的错误 那么这个时候就好好的翻一番你的views代码有没有错误 *** QueryDict 类似字典,但是一个键可以对应多个值 取值方法有get 和getlist getlist取所有提交的值,get只返回最后一个值 *** 设置cookie *** def set_cookie(request): ”’设置cookies信息”’ response=HttpResponse(‘设置cookies’) # 设置一个cookie信息 名字为num 值为1 response.set_cookie(‘num’,1) return response *** 浏览器获取cookie *** def get_cookie(request): ”’获取cookie信息”’ # 取出cookie num=request.COOKIES[‘num’] return HttpResponse(num) *** 可以用 man_tag= s 多少秒,保存cookie多少秒,还以有一个参数expries 可以设置指定的时间让cookie过期,一共两个参数可以设置cookie的保存时间,默认是关闭浏览器之后cookie过期 *** 让cookie记住用户名 首先从表单中取出username,然后通过HttpResponse或者redicts重定向 从表单中拿到正确的用户名,接着用response.set_cookie=(‘username’,username,max_tag=1000) 然后用return返回response给浏览器就可以设置好了cookie信息了,设置了,还需要从cookie中取出来cookie信息,用if 判断username 是否在request.COOKIE 中,如果是在这里的,说明账号密码都是正确的,那么直接取即就好了,如果不是正确的,前面的记住是没有用的,因为没法登陆到首页, 下面是代码部分 *** def login(request): if ‘username’ in request.COOKIES: username=request.COOKIES[‘username’] else: username=” return render(request,’login.html’,context={‘username’:username}) 判断是cookie是否携带账号 携带账号就设置username等于COOIKES里面的username,并且通过render或者重定向,把携带cookies信息的username传递到前端的模板中用{{}} 来取username用value 自动填充即可 *** def cheak_login(request): username=request.POST.get(‘username’) password=request.POST.get(‘password’) # 获取勾选框信息 remember=request.POST.get(‘rename’) # 模拟登录 if username==’123′ and password==’123′: if remember == ‘on’: # 正确就跳转到首页 response=redirect(reverse(‘login:index’)) # 返回值是一个HttpResponse 子类的对象 # 通过HttpResponse 子类对象redirect设置cookie保存用户名 response.set_cookie(‘username’,username,max_age=1000) # 返回cookie信息给浏览器 return response else: # 如果没有勾选记住密码也直接返回首页视图 return redirect(reverse(‘login:index’)) else: # 错误就继续登录 return redirect(reverse(‘login:login’)) *** session 依赖于cookie 储存在服务器端的 设置session request.session 取值 request.session 设置过期时间 request.session.set_expiry(value) 如果是一个整数就在多少秒之后过期, 如果是0,就是在关闭浏览器后过期, 如果是None,默认是两周后过期 *** session保持登录案例, 首先需要在登录状态逻辑后面加上 request.session[islogin]=True 中括号内的值是什么都无所谓,只是一个标识 然后在登录界面用 *** def login(request): if request.session.has_key(‘islogin’): return redirect(reverse(‘login:index’)) 加上标识判断,如果值是存在的,那么就是登录的状态,直接返回到主页中, 如果不存在,那就返回登录页面继续登录 *** cookie 记住用户名,安全性要求不高 session 涉及到安全性要求比较高的数据 银行卡密码,账户等。 *** 开启csrf 跨站攻击{% csrf_token %} 在模板中加上这句话就就可以避免被跨站攻击了,但是只针对于post请求,get请求是没有防护的