本来今天不想发文的,昨天没发,怪不好意思的
django ?view
URL是Web服务的入口,用户通过浏览器发送过来的任何请求,都是发送到一个指定的URL地址,然后被响应。
随便新建一个Django项目,默认会自动为我们创建一个/project_name/urls.py文件,并且自动包含下面的内容,这就是项目的根URL:
配置media媒体文件settings.py
#?媒体文件配置 MEDIA_URL?=?'/media/' MEDIA_ROOT?=?os.path.join(BASE_DIR,?'media')
url.py
确保在渲染的html渲染对应的媒体文件
from?django.urls?import?path,include from?django.conf?import?settings from?django.conf.urls.static?import??static urlpatterns?=?[ ????#?path('admin/',?admin.site.urls), ????path('myadmin/',include('myadmin.urls')), ????path('',include('news.urls')), ????path('',include('verification.urls')), ????path('course/',include('course.urls')), ????path('doc/',include('doc.urls')), ????path('user/',include('user.urls')), ????path('ckeditor/',include('ckeditor_uploader.urls')), ]?+?static(settings.MEDIA_URL,document_root?=?settings.MEDIA_ROOT)
需要在urlpatterns 列表后面加上? static(settings.MEDIA_URL,document_root = settings.MEDIA_ROOT)
include 指的就是包含该app下的url
对于大部分的view视图一般写成类的形式from??django.views?import?View class?IndexView(View): ????''' ????在线课堂首页面 ????''' ????def?get(self,request): ????????#?1.?拿到所有的视频数据 ????????courses?=?Course.objects.only('title','cover_url','teacher__name','teacher__title').select_related('teacher').filter(is_delete?=?False) ????????return?render(request,'course/course.html',context=?{'courses':courses}) class?CourseDetailView(View): ????''' ????课程详细页 ????url?:/course/<int:course_id>/ ????''' ????def?get(self,request,course_id): ????????#?1.?拿到课程信息 ????????course?=?Course.objects.only('title','cover_url','video_url','profile','outline','teacher__name','teacher__photo','teacher__title','teacher__profile').select_related('teacher').filter(is_delete?=?False,id?=?course_id) ????????#?2.?渲染html ????????if?course: ????????????course?=?course[0] ????????????return??render(request,'course/course_detail.html',context={'course':course}) ????????else: ????????????return??Http404('此课程不存在')
对应的url就使用as_view()函数方法
from?django.urls?import?path from??.?import?views app_name?=?'course' urlpatterns?=?[ ????path('',views.IndexView.as_view(),name?=?'index'), ????path('<int:course_id>/',views.CourseDetailView.as_view(),name?=?'course_detail'), ]视图一般编写步骤
拿到对应数据库的模型对象
渲染到对于的html页面
在类中有三个重要的访问函数方法get ?
就是当我访问当url是,就是执行get的方法
def?get(self,?request): ????return?render(request,?'user/login.html')
post
class?LoginView(View): ????""" ????登录视图 ??? url:?/user/login/ ????""" ????def?get(self,?request): ????????return?render(request,?'user/login.html') ????def?post(self,?request): ????????#?1.先校验 ????????#?loginform是登录的表单,在form.py编写导入 ????????form?=?LoginForm(request.POST,?request=request) ????????if?form.is_valid(): ????????????return?json_response(errmsg='恭喜登录成功!') ????????else: ????????????#?将表单的报错信息进行拼接 ????????????err_msg_list?=?[] ????????????for?item?in?form.errors.values(): ????????????????err_msg_list.append(item[0]) ????????????err_msg_str?=?'/'.join(err_msg_list) ????????????return?json_response(errno=Code.PARAMERR,?errmsg=err_msg_str)
如当我登录的时候就会访问登录的界面发送get请求,提交数据在数据库就是post请求
put
put请求容易给人忽视,用于修改,当要修改用户的数据
class?UserUpdateView(View): ????""" ????用户更新视图 ????url:/myadmin/user/<int:user_id>/ ????def?get(self,?request,?user_id): ????????user?=?User.objects.filter(id=user_id).first() ????????if?user: ????????????form?=?UserModelForm(instance=user) ????????else: ??????????? return json_response(errno=Code.NODATA, errmsg='没有此用户!') ????????return?render(request,?'myadmin/user/user_detail.html',?context={'form':?form}) ????""" ????def?put(self,?request,?user_id): ????????#?1.?拿到要修改的用户对象 ????????user?=?User.objects.filter(id=user_id).first() ????????#?1.1?判断用户是否存在 ????????if?not?user: ????????????return?json_response(errno=Code.NODATA,?errmsg='没有此用户!') ????????#?2.?拿到前端传递的参数 ????????put_data?=?QueryDict(request.body) ????????#?3.?校验参数 ????????#?3.1?创建表单对象 ????????#?UserModelForm在form.py自定义的 ????????form?=?UserModelForm(put_data,?instance=user) ????????if?form.is_valid(): ????????????#?4.?如果成功,保存数据 ????????????form.save() ????????????return?json_response(errmsg='用户修改成功!') ????????else: ????????????#?5.?如果不成功就返回渲染了错误提示信息的页面 ????????????return?render(request,?'myadmin/user/user_detail.html',?context={'form':?form})QueryDict
>>>?QueryDict('a=1&a=2&c=3') <QueryDict:?{'a':?['1',?'2'],?'c':?['3']}>
一般我们看到的数据就是json的键值对,而不是列表
request.body就是form表单的数据
Queryset
Django ORM用到三个类:Manager、QuerySet、Model。
Manager定义表级方法(表级方法就是影响一条或多条记录的方法),我们可以以models.Manager为父类,定义自己的manager,增加表级方法;
QuerySet:Manager类的一些方法会返回QuerySet实例
就是从数据库根据自己要求拿数据的连数据都那不出来,写啥视图
所以在编写queryset必须用django shell 调试
在model中,Django通过给Model增加一个objects属性来提供数据操作大的接口。比如:想要查询所有评论的数据,可以这么写:
Comments.objects.all() #?可切片 Comments.objects.all()[0:1] #?可迭代 for?coment?in?comments: ????print(comment.author?)
exists() 判断是否存在
难度提升
doc model
#?is_delete是继承baseModel docs?=?Doc.objects.values('file_url','file_name','title','desc','image_url').filter(is_delete=?False)
现在拿到没有删除的部分数据,不拿author字段
app.object的用法
filter() ? ?过滤查询对象。
exclude() ? ?排除满足条件的对象
annotate() ? ?使用聚合函数
order_by() ? ?对查询集进行排序
reverse() ? ?反向排序
distinct() ? ?对查询集去重
values() ? ?返回包含对象具体值的字典的QuerySet
values_list() ? ?与values()类似,只是返回的是元组而不是字典。
dates() ? ?根据日期获取查询集
datetimes() ? ?根据时间获取查询集
none() ? ?创建空的查询集
all() ? ?获取所有的对象
union() ? ?并集
intersection() ? ?交集
difference() ? ?差集
select_related() ? ?附带查询关联对象
prefetch_related() ? 预先查询
extra() ? ?附加SQL查询
defer() ? ?不加载指定字段
only() ? ?只加载指定的字段
using() ? ?选择数据库
select_for_update()
raw()
raw() 使用sql不熟悉SQL的可以跳过该部分,如下代码: sql?=?'select?*?from?new'?#需要查询数据库具体new对应表名 qs?=?new.objects.raw(sql)?#将sql语句转成RawQuerySet对象 该SQL是获取全部记录,相当于QuerySet如下查询: qs?=?new.objects.all()filter()
filter是筛选的意思,通过filter筛选得到符合条件的数据集。
tags?=?Tag.objects.only('name').filter(is_delete=False)values() ?only()
返回的是queryset字典,不是对象,only才是返回的是对象
?docs?=?Doc.objects.values('file_url','file_name','title','desc','image_url').filter(is_delete=?False) docs?=?Doc.objects.only('file_url','file_name','title','desc','image_url').filter(is_delete=?False)select_related()
如果我要拿这个模型通过外键绑定的另外一个模型,使用select_related
course 模型定义了teacher字段绑定teacher模型
course?=?Course.objects.only('title','cover_url','video_url','profile','outline','teacher__name','teacher__photo','teacher__title','teacher__profile').select_related('teacher').filter(is_delete?=?False,id?=?course_id)重点
官方文档:https://docs.djangoproject测试数据/en/2.1/topics/db/aggregation/
Django的aggregate和annotate方法属于高级查询方法,主要用于组合查询,是Django高手们必需要熟练掌握的。当我们需要对查询集(queryset)的某些字段进行计算或进行先分组再计算或排序, 我们就需要使用aggregate和annotate方法了。
aggregate
下面代码来源官网
from?django.db?import?models class?Author(models.Model): ????name?=?models.CharField(max_length=100) ????age?=?models.IntegerField() class?Publisher(models.Model): ????name?=?models.CharField(max_length=300) class?Book(models.Model): ????name?=?models.CharField(max_length=300) ????pages?=?models.IntegerField() ????price?=?models.DecimalField(max_digits=10,?decimal_places=2) ????rating?=?models.FloatField() ????authors?=?models.ManyToManyField(Author) ????publisher?=?models.ForeignKey(Publisher,?on_delete=models.CASCADE) ????pubdate?=?models.DateField() class?Store(models.Model): ????name?=?models.CharField(max_length=300) ????books?=?models.ManyToManyField(Book) >>>?Book.objects.count() 2452 #?publisher__name?是?book通过publisher绑定的app下的name字段,写成publisher__name >>>?Book.objects.filter(publisher__name='BaloneyPress').count() 73 #?Average?price?across?all?books. >>>?from?django.db.models?import?Avg >>>?Book.objects.all().aggregate(Avg('price')) {'price__avg':?34.35} #?Max?price?across?all?books. >>>?from?django.db.models?import?Max >>>?Book.objects.all().aggregate(Max('price')) {'price__max':?Decimal('81.20')}annotate
先介绍F,annotate 必用F
F介绍-个F()对象表示一个模型字段或注释的列的值。这样就可以引用模型字段值并使用它们执行数据库操作,而无需实际将它们从数据库中拉出到Python内存中
说白了就是我从数据库拿东西,但是有些需要的字段没有,要通过绑定的外键的app的model拿。但是名称又是app__字段来命名,这样我要改名称,而且拿第一次的model,放在python内存中,再拿通过外键绑定的另一个model,又要执行第一次步骤,那个效率就不行了,干嘛我不一起拿,所以会用annotate可以提高效率
from?django.db.models?import?F banners?=?Banner.objects.values('image_url',?'news_id').annotate(news_title=F('news__title')).filter(is_delete=False)
我要拿出image_url,news_id,和news_title,news_title来源banner模型外键绑定news中的title字段,拿出来它叫news__title,我要给它换个名字叫news_title,这就是注释。