Django项目知识点(四)

举报
毛利 发表于 2021/07/15 07:00:01 2021/07/15
【摘要】 https://mp.weixin.qq.com/s/8yznCfBdbgzy8ZN7tiRTEw 本来今天不想发文的,昨天没发,怪不好意思的 django view URL是Web服务的入口,用户通过浏览器发送过来的任何请求,都是发送到一个指定的URL地址,然后被响应。 随便新建一个Django项目,默认会自动为我们创建一个/project_name/urls....

https://mp.weixin.qq.com/s/8yznCfBdbgzy8ZN7tiRTEw

本来今天不想发文的,昨天没发,怪不好意思的
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)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

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('此课程不存在')

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

对应的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'),
]

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

视图一般编写步骤

  • 拿到对应数据库的模型对象
  • 渲染到对于的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)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

如当我登录的时候就会访问登录的界面发送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})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

QueryDict

>>> QueryDict('a=1&a=2&c=3')
<QueryDict: {'a': ['1', '2'], 'c': ['3']}>
一般我们看到的数据就是json的键值对,而不是列表

  
 
  • 1
  • 2
  • 3

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()

  
 
  • 1
  • 2
  • 3

可切片

Comments.objects.all()[0:1]

  
 
  • 1

可迭代

for coment in comments: print(comment.author ) 

  
 
  • 1
  • 2

exists() 判断是否存在
难度提升

doc model


  
 
  • 1
  • 2

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.com/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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

publisher__name 是 book通过publisher绑定的app下的name字段,写成publisher__name

>>> Book.objects.filter(publisher__name='BaloneyPress').count()
73

  
 
  • 1
  • 2

Average price across all books.

>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

  
 
  • 1
  • 2
  • 3

Max price across all books.

>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')}
annotate

  
 
  • 1
  • 2
  • 3
  • 4

先介绍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)

  
 
  • 1
  • 2

我要拿出image_url,news_id,和news_title,news_title来源banner模型外键绑定news中的title字段,拿出来它叫news__title,我要给它换个名字叫news_title,这就是注释。

文章来源: maoli.blog.csdn.net,作者:刘润森!,版权归原作者所有,如需转载,请联系作者。

原文链接:maoli.blog.csdn.net/article/details/102599622

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。