好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Django项目知识点(四)

本来今天不想发文的,昨天没发,怪不好意思的

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,这就是注释。

查看更多关于Django项目知识点(四)的详细内容...

  阅读:52次