Loading

day 60 初识Django框架

1 初识

1.1 三大主流框架

三大主流框架有

django
特点:大而全,自带的功能特别特别特别的多,类似于航空母舰
不足之处:有时候过于笨重

flask
特点:
                小而精,自带的功能特别特别特别的少,类似于游骑兵。第三方的模块特别特别特别的多,如果将flask第三方
                的模块加起来完全可以盖过django,并且也越来越像django
不足之处:
比较依赖于第三方的开发者

tornado
特点:异步非阻塞,支持高并发,牛逼到甚至可以开发游戏服务器
不足之处:暂时你不会

框架三部分对比

对比以下三部分:
        A:socket部分
        B:路由与视图函数对应关系(路由匹配)
        C:模版语法
---------------------------------------------------
django
  A用的是别人的:wsgiref模块
  B用的是自己的
  C用的是自己的(没有jinja2好用,但是也很方便)
---------------------------------------------------
flask
  A用的是别人的:werkzeug(内部还是wsgiref模块)
  B自己写的
  C用的别人的(jinja2)
---------------------------------------------------
tornado
A,B,C都是自己写的

​ 使用 Django,只要很少的代码,Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务。 Django 本身基于 MVC 模型,即 Model(模型)+ View(视图)+ Controller(控制器)设计模式,MVC 模式使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。

1.2 MVC 与 MTV模型

MVC 模型

​ MVC 模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

MVC 以一种插件式的、松耦合的方式连接在一起。

  • 模型(M)- 编写程序应有的功能,负责业务对象与数据库的映射(ORM)。

  • 视图(V)- 图形界面,负责与用户的交互(页面)。

  • 控制器(C)- 负责转发请求,对请求进行处理。

    img

MTV 模型

​ Django 的 MTV 模式本质上和 MVC 是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django 的 MTV 分别是指:

  • M 表示模型(Model):编写程序应有的功能,负责业务对象与数据库的映射(ORM)。
  • T 表示模板 (Template):负责如何把页面(html)展示给用户。
  • V 表示视图(View):负责业务逻辑,并在适当时候调用 Model和 Template。

除了以上三层之外,还需要一个 URL 分发器,它的作用是将一个个 URL 的页面请求分发给不同的 View 处理,View 再调用相应的 Model 和 Template,MTV 的响应模式如下所示:

简易图:

img

1.3 注意事项

# 如何让你的计算机能够正常的启动django项目
  1.计算机的名称不能有中文
  2.一个pycharm窗口只开一个项目
  3.项目里面所有的文件也尽量不要出现中文
  4.python解释器尽量使用3.4~3.6之间的版本
  (如果你的项目报错,你点击最后一个报错信息,去源码中把逗号删掉)
---------------------------------------------------------------------------- 
# django版本问题
  1.X 2.X 3.X(直接忽略)
  1.X和2.X本身差距也不大 我们讲解主要以1.X为例 会讲解2.X区别
  公司之前用的1.8 满满过渡到了1.11版本 有一些项目用的2.0
 ----------------------------------------------------------------------------
# django安装
pip3 install django==1.11.11
  如果已经安装了其他版本 ,无需自己卸载,直接重新装 ,会自动卸载安装新的
  
  如果报错 ,看看是不是timeout ,如果是 那么只是网速波动,重新安装即可
  
  验证是否安装成功的方式,终端输入django-admin看看有没有反应

2 django基本操作

如果使用的是我们自定义的框架来开发web应用,需要事先生成框架包含的一系列基础文件,然后在此基础上进行开发。

如果使用的是Django框架来开发web应用,同样需要事先生成Django框架包含的一系列基础文件,然后在此基础上进行开发。

但Django框架更为方便的地方在于它已经为我们提供了一系列命令来帮我们快速地生成这一系列基础文件

2.1 创建一个django项目:

下面的命令创建了一个名为"mysite"的Django 项目:在命令行执行以下指令,会在当前目录生成一个名为mysite的文件夹,该文件夹中包含Django框架的一系列基础文件

django-admin startproject mysite

项目建好后会创建这个文件夹:

mysite/  # 总文件夹
├── manage.py  # 管理文件
└── mysite  # 项目目录文件夹
    ├── __init__.py
    ├── settings.py  # 配置
    ├── urls.py  # 路由 --> URL和函数的对应关系
    └── wsgi.py  # runserver命令就使用wsgiref模块做简单的web server

2.2 运行Django项目:

启动项目一定要先切换到项目目录下:cd /mysite

python manage.py runserver 127.0.0.1:8000
# 或者python3 manage.py runserver

启动后会返回一个网址,即当前服务器的网址:http://127.0.0.1:8000/

2.3 创建应用

创建项目后会提示你:

Next, start your first app by running python manage.py startapp [app_label].

创建应用

python manage.py startapp app01
应用名应该做到见名知意
  user
  order
  web

2.4 pycharm操作

以上三步在 pycharm 中是如何操作的

# 1 new project 选择左侧第二个django即可
  
# 2 启动
  1.在team终端还是用命令行启动
      2.点击绿色小箭头即可

# 3 创建应用:python manage.py startapp app01
       1.pycharm提供的终端直接输入完整命令
    2.pycharm 
      tools 
        run manage.py task提示
                
 # 4 修改端口号以及创建server
edit confi....

2.5 注意点

django是一款专门用来开发app的web框架

django框架就类似于是一所大学(空壳子)
app就类似于大学里面各个学院(具体功能的app)
比如开发淘宝
    订单相关
    用户相关
    投诉相关
创建不同的app对应不同的功能

    选课系统
    学生功能
    老师功能

一个app就是一个独立的功能模块
****创建的应用一定要去配置文件中注册****

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',  # 全写
  'app01',      # 简写
]

# 创建出来的的应用第一步先去配置文件中注册,其他的先不要给我干
ps:你在用pycharm创建项目的时候, pycharm可以帮你创建一个app并且自动注册

2.6 主要文件介绍

随着业务逻辑复杂度的增加,处理业务逻辑的函数以及url_patterns中的映射关系都会不断地增多,此时仍然把所有代码都放到一个文件中,程序的可读性和可扩展性都会变得非常差,所以我们应该将现有的代码拆分到不同文件中

img

mysite  # 文件夹
    ├── app01  # 文件夹
    │   └── migrations  # 文件夹,数据库迁移记录
    │   └── admin.py  # django后台管理
    │   └── apps.py  # 注册使用
    │   └── models.py  # 数据库相关的模型类(orm)
    │   └── tests.py  # 数据库相关的模型类(orm)
    │   └── views.py  # 数据库相关的模型类(orm)
    ├── mysite # 文件夹
    │   └── settings.py  # 配置文件
    │   └── urls.py #  路由与视图函数对应关系(路由层)
    │   └── wsgi.py # wsgiref模块(不考虑)
    │   └── manage.py# django的入口文件
    │   └── db.sqlite3#  django自带的sqlite3数据库(小型数据库 功能不是很多还有bug)
    └── templates # 文件夹
├── manage.py)

2.7 命令行与pycharm创建的区别

# 1 命令行创建不会自动有templatew文件夹 ,需要你自己手动创建,而pycharm会自动帮你创建,并且还会自动在配置文件中配置对应的路径

# pycharm创建
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
]
        
# 命令行创建
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
]

# 也就意味着你在用命令行创建django项目的时候,不单单需要创建templates文件夹,还需要去配置文件中配置路径
'DIRS': [os.path.join(BASE_DIR, 'templates')]

2.8 django小白必会三板斧

from django.shortcuts import HttpResponse, render, redirect

2.8.1 HttpResponse

内部传入一个字符串参数,返回给浏览器。

def index(request):
    # 业务逻辑代码
    return HttpResponse("OK")

Response对象

与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。我们写的每个视图都需要实例化,填充和返回一个HttpResponse。

HttpResponse类位于django.http模块中。

使用

传递字符串

from django.http import HttpResponse
response = HttpResponse("Here's the text of the Web page.")
response = HttpResponse("Text only, please.", content_type="text/plain")

设置或删除响应头信息

response = HttpResponse()
response['Content-Type'] = 'text/html; charset=UTF-8'
del response['Content-Type']

属性

HttpResponse.content:响应内容

HttpResponse.charset:响应内容的编码

HttpResponse.status_code:响应的状态码

JsonResponse对象

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

from django.http import JsonResponse

response = JsonResponse({'foo': 'bar'})
print(response.content)

b'{"foo": "bar"}'

默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。

response = JsonResponse([1, 2, 3], safe=False)

2.8.2 render

除request参数外,还接受一个待渲染的模板文件,和一个保存具体数据的字典参数。

将数据填充进模板文件,最后把结果返回给浏览器。(类似于我们上面用到的jinja2)

def index(request):
    # 业务逻辑代码
    return render(request, "index.html", {"name": "alex", "hobby": ["烫头", "泡吧"]})

2.8.3 redirect

接受一个URL参数,表示跳转到指定的URL。

def index(request):
    # 业务逻辑代码
    return redirect('https://www.mzitu.com/')
    return redirect('/home/')

重定向是怎么回事?

img

2.8.4 基于Django实现的一个简单示例

(1)url.py

Copyfrom django.contrib import admin
from django.conf.urls import url
#导入views模块
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    # r'^index/$' 会正则匹配url地址的路径部分
    url(r'^index/$',views.index), # 新增地址http://127.0.0.1:8001/index/与index函数的映射关系
]

(2)视图

Copyfrom django.shortcuts import render

# 必须定义一个request形参,request相当于我们自定义框架时的environ参数
def index(request):
    import datetime
    now=datetime.datetime.now()
    ctime=now.strftime("%Y-%m-%d %X")

    return render(request,"index.html",{"ctime":ctime}) # render会读取templates目录下的index.html文件的内容并且用字典中的ctime的值替换模版中的{{ ctime }}

(3)模版

在templates目录下新建文件index.html

Copy<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>当前时间:{{ ctime }}</h4>

</body>
</html>

测试:

Copypython manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/index/ 会看到当前时间。

2.9 静态文件配置

2.9.1 介绍

我们将html文件默认都放在templates文件夹下,我们将网站所使用的静态文件默认都放在static文件夹下。

静态文件:前端已经写好了的 能够直接调用使用的文件

网站写好的js文件
网站写好的css文件
网站用到的图片文件
第三方前端框架
...
拿来就可以直接使用的

django默认是不会自动帮你创建static文件夹,需要你自己手动创建,一般情况下我们在static文件夹内还会做进一步的划分处理

-static
     --js
    --css
    --img
    其他第三方文件

注意:在浏览器中输入url能够看到对应的资源,是因为后端提前开设了该资源的接口,如果访问不到资源 说明后端没有开设该资源的接口

当你在写django项目的时候,可能会出现后端代码修改了,但是前端页面没有变化的情况,这可能是因为:
1.你在同一个端口开了好几个django项目,一直在跑的其实是第一个django项目

2.浏览器缓存的问题,解决办法
settings
network
disable cache 勾选上

2.9.2 静态文件配置

因为静态文件经常访问,所以Django帮我们写好了一个静态文件访问机制,我们就不需要自己再去写路由视图函数了,Django只要检测到请求中有static就明白了我们要访问静态文件

静态文件配置
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "template")],  # template文件夹位置
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

在setting中静态文件配置。STATIC_URL = '/ooo/' 类似于访问静态文件的令牌,如果你想要访问静态文件,你就必须以令牌/ooo开头。

当你发来令牌时,Django明白你要访问静态文件了,这时Django回去下面配置的地点中找你需要的文件发给你

STATIC_URL = '/static/'  # HTML中使用的静态文件夹前缀
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),  # 静态文件存放位置
    os.path.join(BASE_DIR,'static1'),
    os.path.join(BASE_DIR,'static2'),
]

如果你的令牌经常需要修改,频繁去修改HTML文件里的访问令牌名会很麻烦,Django提供了一个动态令牌名解析机制

# 静态文件动态解析
 {% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>

查找顺序就是从上往下依次查找,查找到一个就不会继续往下找了所以可能会出现替换的情况

img

# form表单默认是 get请求数据
http://127.0.0.1:8000/login/?username=jason&password=123
form表单action参数
1.不写 默认朝当前所在的url提交数据
2.全写 指名道姓
3.只写后缀 /login/,会自动拼接当前页面网址

刚开始学习时可在配置文件中暂时禁用csrf中间件,方便表单提交测试。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',  把这行注释掉
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

3 request对象方法初识

Django 使用请求和响应对象通过系统传递状态。

当请求页面时,Django会创建一个包含有关请求的元数据的HttpRequest对象。然后 Django 加载适当的视图,将HttpRequest作为第一个参数传递给视图函数。每个视图负责返回一个HttpResponse对象。
Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。

[官方文档](Request and response objects | Django documentation | Django (djangoproject.com))

3.1 请求相关的常用值

  • path_info:返回用户访问url,不包括域名

  • method:请求中使用的HTTP方法的字符串表示,全大写表示。

  • GET:包含所有HTTP GET参数的类字典对象

  • POST:包含所有HTTP POST参数的类字典对象

  • body:请求体,byte类型 request.POST的数据就是从body里面提取到的

3.2 属性

所有的属性应该被认为是只读的,除非另有说明。

request对象属性
属性:
  django将请求报文中的请求行、头部信息、内容主体封装成 HttpRequest 类中的属性。除了特殊说明的之外,其他均为只读的。


0.HttpRequest.scheme
   表示请求方案的字符串(通常为http或https)

1.HttpRequest.body

  一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。

  但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。

  另外,我们还可以用 python 的类文件方法去操作它,详情参考 HttpRequest.read() 。

 

2.HttpRequest.path
  一个字符串,表示请求的路径组件(不含域名)。
  例如:"/music/bands/the_beatles/"



3.HttpRequest.method
  一个字符串,表示请求使用的HTTP 方法。必须使用大写。
  例如:"GET"、"POST"

 

4.HttpRequest.encoding
  一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。
   这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。
   接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。
   如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。

 

5.HttpRequest.GET 
  一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。

 

6.HttpRequest.POST
  一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。
  POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。
   因此,不应该使用 if request.POST  来检查使用的是否是POST 方法;应该使用 if request.method == "POST" 
  另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。

 7.HttpRequest.COOKIES
  一个标准的Python 字典,包含所有的cookie。键和值都为字符串。

 

8.HttpRequest.FILES
  一个类似于字典的对象,包含所有的上传文件信息。
   FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
  注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会
   包含数据。否则,FILES 将为一个空的类似于字典的对象。

 

9.HttpRequest.META
   一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:
                CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
                CONTENT_TYPE —— 请求的正文的MIME 类型。
                HTTP_ACCEPT —— 响应可接收的Content-Type。
                HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
                HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
                HTTP_HOST —— 客服端发送的HTTP Host 头部。
                HTTP_REFERER —— Referring 页面。
                HTTP_USER_AGENT —— 客户端的user-agent 字符串。
                QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
                REMOTE_ADDR —— 客户端的IP 地址。
                REMOTE_HOST —— 客户端的主机名。
                REMOTE_USER —— 服务器认证后的用户。
                REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
                SERVER_NAME —— 服务器的主机名。
                SERVER_PORT —— 服务器的端口(是一个字符串)。
   从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_  前缀。
所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。

 
10.HttpRequest.user
  一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。
  如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。

    例如:
    if request.user.is_authenticated():
        Do something for logged-in users.
    else:
        Do something for anonymous users.
     

#  user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。

     -------------------------------------------------------------------------------------

    匿名用户
    class models.AnonymousUser

    django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点:

    id 永远为None。
    username 永远为空字符串。
    get_username() 永远返回空字符串。
    is_staff 和 is_superuser 永远为False。
    is_active 永远为 False。
    groups 和 user_permissions 永远为空。
    is_anonymous() 返回True 而不是False。
    is_authenticated() 返回False 而不是True。
    set_password()、check_password()、save() 和delete() 引发 NotImplementedError。
    New in Django 1.8:
    新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。

 

11.HttpRequest.session

   一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。
request.method    # 返回请求方式 ,并且是全大写的字符串形式  <class 'str'>

request.POST        # 获取用户,post请求提交的普通数据不包含文件
request.POST.get()  # 只获取列表最后一个元素
request.POST.getlist()  # 直接将列表取出
    
request.GET                     # 获取用户提交的get请求数据
request.GET.get()       # 只获取列表最后一个元素
request.GET.getlist()  # 直接将列表取出
"""
get请求携带的数据是有大小限制的,大概只有4KB左右
而post请求则没有限制
"""

示例

 def login(request):
    # 返回一个登陆界面
    """
    get请求和post请求应该有不同的处理机制
    :param request: 请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    print(type(request.method))  # 返回请求方式,并且是全大写的字符串形式  <class 'str'>
    
    if request.method == 'GET':
         print('来了 老弟')
         return render(request,'login.html')
    elif request.method == 'POST':
         return HttpResponse("收到了 宝贝")
    ------------------------------------------------------------
   #  第二种写法:
    if request.method == 'POST':
        return HttpResponse("收到了 宝贝")
    return render(request, 'login.html')

4 链接数据库(MySQL)

4.1 pycharm链接数据库(MySQL)

三个位置查找数据库相关
右侧上方database
左下方database
配置里面的plugins插件搜索安装

再没有卸载pycharm重新装

pycharm可以充当很多款数据库软件的客户端。链接前需要提前创建好库

4.2 django链接数据库(MySQL)

1.第一步配置文件中配置:django默认用的数据库是sqkite3,我们需要去配置文件里修改配置。;另外链接数据库时记得安装驱动

# 原配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
# 修改后
  DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day60',
        'USER':'root',
        'PASSWORD':'admin123',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'CHARSET':'utf8'
    }
}

2.第二步代码声明:django默认用的是mysqldb模块链接MySQL,但是该模块的兼容性不好,需要手动改为用pymysql链接,你需要告诉django不要用默认的mysqldb,变成用pymysql

# 在项目名下的init,或者任意的应用名下的init文件中,书写以下代码都可以
import pymysql
pymysql.install_as_MySQLdb()

4.5 Django ORM初识

4.5.1 介绍

Django 模型使用自带的 ORM。

对象关系映射(Object Relational Mapping,简称 ORM )用于实现面向对象编程语言里不同类型系统的数据之间的转换。

ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。

ORM 是通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。

img

使用 ORM 的好处:

提高开发效率。
不同数据库可以平滑切换。

使用 ORM 的缺点

ORM 代码转换为 SQL 语句时,需要花费一定的时间,执行效率会有所降低。
长期写 ORM 代码,会降低编写 SQL 语句的能力。

ORM 解析过程:

1、ORM 会将 Python 代码转成为 SQL 语句。
2、SQL 语句通过 pymysql 传送到数据库服务端。
3、在数据库中执行 SQL 语句并将结果返回。

ORM 对象关系映射

作用:能够让一个不用sql语句的小白也能够通过python 面向对象的代码简单快捷的操作数据库
不足之处:封装程度太高,有时候sql语句的效率偏低,需要你自己写SQL语句

类     表
对象   记录
对象属性记录某个字段对应的值

img

4.5.2 应用

1 先去models.py中书写类

class User(models.Model):
        # id int primary_key auto_increment
        id = models.AutoField(primary_key=True)

        # username varchar(32)
        username = models.CharField(max_length=32)

        # password int
        password = models.IntegerField()
        
        
class User(models.Model):
    # id int primary_key auto_increment。 verbose_name该参数是所有字段都有的 就是用来对字段的解释
    id = models.AutoField(primary_key=True,verbose_name='主键')
    
    # username varchar(32)。CharField必须要指定max_length参数,不指定会直接报错
    username = models.CharField(max_length=32,verbose_name='用户名')
    
    # password int
    password = models.IntegerField(verbose_name='密码')


class Author(models.Model):
    # 由于一张表中必须要有一个主键字段,并且一般情况下都叫id字段
    # 所以orm当你不定义主键字段的时候,orm会自动帮你创建一个名为id主键字段
    # 也就意味着,后续我们在创建模型表的时候,如果主键字段名没有额外的叫法,那么主键字段可以省略不写
    
    # username varchar(32)
    username = models.CharField(max_length=32)
    
    # password int
    password = models.IntegerField()

2 数据库迁移命。 只要你修改了models.py中跟数据库相关的代码 就必须重新执行上述的两条命令

python3 manage.py makemigrations  # 将操作记录记录到小本本上(migrations文件夹)

python3 manage.py migrate   # 将操作真正的同步到数据库中

4.6 字段的增删改查

字段的增加

1.可以在终端内直接给出默认值

2.该字段可以为空
    info = models.CharField(max_length=32,verbose_name='个人简介',null=True)
    
3.直接给字段设置默认值
    hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='study')

字段的修改

直接修改代码然后执行数据库迁移的两条命令即可!

字段的删

直接注释对应的字段然后执行数据库迁移的两条命令即可!
执行完毕之后字段对应的数据也都没有了
在操作models.py的时候一定要细心
千万不要轻易注释一些字段,执行迁移命令之前最好先检查一下自己写的代码

当你离开你的计算机之后一定要锁屏

4.7 数据的增删改查

res = models.User.objects.filter(username=username)
返回值你先看成是列表套数据对象的格式
它也支持索引取值,切片操作,但是不支持负数索引,它也不推荐你使用索引的方式取值
filter括号内可以携带多个参数,参数与参数之间默认是and关系,你可以把filter联想成where记忆
user_obj = models.User.objects.filter(username=username).first()

增:返回值就是当前被创建的对象本身

# 第一种增加
from app01 import models
res = models.User.objects.create(username=username,password=password)
# 第二种增加
user_obj = models.User(username=username,password=password)
user_obj.save()  # 保存数

应用:先将数据库中的数据全部展示到前端,然后给每一个数据两个按钮,一个编辑一个删除

先查询

查询出用户表里面所有的数据
def userlist(request):
    
        # 方式1
        data = models.User.objects.filter()
        print(data)

        # 方式2
        user_queryset = models.User.objects.all()
        # return render(request,'userlist.html',{'user_queryset':user_queryset})
        return render(request,'userlist.html',locals())

修改

编辑功能
# 点击编辑按钮朝后端发送编辑数据的请求,这时有一个问题:如何告诉后端用户想要编辑哪条数据?
# 解决办法:利用url问号后面携带参数的方式,将编辑按钮所在的那一行数据的主键值发送给后端
-------------------------------------------------------------------------------
# HTML
{% 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')
                
                # 去数据库中修改对应的数据内容
                # 修改数据方式1:将filter查询出来的列表中所有的对象全部更新,批量更新操作,只修改被修改的字段
                models.User.objects.filter(id=edit_id).update(username=username,password=password)

                # 修改数据方式2:这个方法当字段特别多的时候效率会非常的低,从头到尾将数据的所有字段全部更新一边 无论该字段是否被修改
                edit_obj.username = username
                edit_obj.password= password
                edit_obj.save()
  
                # 跳转到数据的展示页面
                return redirect('/userlist/')

        # 将数据对象展示到页面上
        return render(request,'edit_user.html',locals())
删除功能
# 跟编辑功能逻辑类似

def delete_user(request):
    # 获取用户想要删除的数据id值
    delete_id = request.GET.get('user_id')
    
    # 直接去数据库中找到对应的数据删除即可
    models.User.objects.filter(id=delete_id).delete()

    # 跳转到展示页面
    return redirect('/userlist/')
-------------------------------------------------------------

真正的删除功能应该需要二次确认,我们这里先不做后面会讲
删除数据,服务器内部其实并不是真正的删除,我们会给数据添加一个标识字段用来表示当前数据是否被删除了,如
果数据被删了仅仅只是将字段修改一个状态:
username password  is_delete
  jason   123         0
  egon1231  234        1

4.8 django orm中如何创建表关系

表与表之间的关系
一对多
多对多
一对一
没有关系

判断表关系的方法:换位思考
-----------------------------------------
图书表
出版社表
作者表
作者详情表
-----------------------------------------
图书和出版社是一对多的关系,外键字段建在多的那一方 book
图书和作者是多对多的关系,需要创建第三张表来专门存储
作者与作者详情表是一对一
点击查看代码
from django.db import models
# Create your models here.

# 创建表关系:先将基表创建出来,然后再添加外键字段
class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8,decimal_places=2)     # 总共八位,小数点后面占两位

        publish = models.ForeignKey(to='Publish') 
        """
        默认就是与出版社表的主键字段做外键关联,图书和出版社是一对多,并且书是多的一方,所以外键字段放在书表里面
        如果字段对应的是ForeignKey,那么会orm会自动在字段的后面加_id,如果你自作聪明的加了_id,那么orm还是会在后面继续加_id,后面在定义ForeignKey的时候就不要自己加_id
        """ 

        authors = models.ManyToManyField(to='Author')
        """
        图书和作者是多对多的关系,外键字段建在任意一方均可,但是推荐你建在查询频率较高的一方
        authors是一个虚拟字段,主要是用来告诉orm,书籍表和作者表是多对多关系,然后让orm自动帮你创建第三张关系表
        """
    
--------------------------------------------------------
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')
        """
        作者与作者详情是一对一的关系,外键字段建在任意一方都可以,但是推荐你建在查询频率较高的表中
        OneToOneField也会自动给字段加_id后缀,所以你也不要自作聪明的自己加_id
        """
--------------------------------------------------------
class AuthorDetail(models.Model):
        phone = models.BigIntegerField()  # 或者直接字符类型
        addr = models.CharField(max_length=32)


"""

"""

# 在django1.X版本中外键默认都是级联更新删除的
# 多对多的表关系可以有好几种创建方式 这里暂且先介绍一种
# 针对外键字段里面的其他参数 暂时不要考虑 如果感兴趣自己可以百度试试看

orm中如何定义三种关系

publish = models.ForeignKey(to='Publish')  # 默认就是与出版社表的主键字段做外键关联

authors = models.ManyToManyField(to='Author')

author_detail = models.OneToOneField(to='AuthorDetail')

---------------------------------------------------------------------------
ForeignKey与OneToOneField会自动在字段后面加_id后缀

5 django请求生命周期流程图(必会)

综上,我们使用Django框架就是为了开发application,而application的工作过程本质就是根据不同的请求返回不同的数据,Django框架将这个工作过程细分为如下四层去实现

1、路由层(根据不同的地址执行不同的视图函数,详见urls.py)

2、视图层(定义处理业务逻辑的视图函数,详见views.py)

3、模型层 (跟数据库打交道的,详解models.py)

4、模板层(待返回给浏览器的html文件,详见templates)

django请求生命周期

django请求生命周期

每个人都要会画,这个图是你们后期复习django最好的一个梳理方式

img

6 总结

纯手撸web框架

"""
1.socket代码需要我们自己写
2.http格式的数据自己处理(只能拿到用户输入的路由)
"""

基于wsgiref模块

"""
1.帮助你封装了socket代码
2.帮你处理http格式的数据(大字典)

web服务网关接口
	1.请求来的时候帮助你自动拆分http格式数据并封装成非常方便处理的数据格式
	2.响应走的时候帮你讲数据再打包成符合http格式
"""

根据功能的不同拆分成不同py文件(关键)

urls.py
	路由与视图函数对应关系
views.py(后端业务逻辑)
	业务逻辑的视图函数
  	ps:视图函数可以是函数其实也可以是类
      面向函数式编程
      面向对象式编程
templates模版文件夹
	存储html文件
# 拆分完成后 后续要想添加功能 只需要在urls.py和views.py中书写对应的代码即可

动静态网页

点击查看代码
# 根据html页面内容是写死的还是从后端动态获取的
	1.后端获取当前时间
  2.从数据库获取数据
  ...
"""
如何讲后端的数据传递给html文件(在后端发生的不在浏览器上)
	1.lowb版本 利用字符串的替换
	2.jinja2模版语法
		即支持给html传数据
		还提供了一系列快捷方式操作数据(模版语法)
			{{ user_list }}
			
			{%for i in user_list %}
			{%enfor%}
		jinja2的模版语法及其的贴近python语法 并且有时候比python语法更加的简单
"""

# 利用wsgiref模块封装的web框架加上jinja2模版语法 结合前端后端数据库

python三大主流web框架

点击查看代码
# 在你没有多少基础的时候切记不要同时学习下面多个,不然容易混淆!!!
"""
django
	大而全  类似于航空母舰
	但是有时候过于笨重
flask
	小而精		类似于游骑兵(单行代码就可以起一个flask服务)
	第三方组件很多 但是有时候也会受限于第三方
tornado
	异步非阻塞
	速度非常快

SANIC
FASTAPI
...
"""

注意事项

点击查看代码
"""
1.计算机名称不能有中文
2.一个pycharm窗口不要打开多个项目(跟不要出现文件夹套文件夹多级目录的出现)
	day01
	day02
	...
3.文件名也不要出现中文
4.python解释器版本建议使用3.6
		如果django安装成功了但是启动就报错
		那么点击报错的那一行将那一行源码的逗号删除即可
5.版本问题
	1.X
	2.X
	LTS维护时间
	两个版本之间差距不大 完全不影响你的学习
	
	
	pip3 install django==1.11.11
	环境变量配置 多版本共存
"""

django必会命令

点击查看代码
# 命令行
	1.创建django项目(先切换到一个盘中D:)
  	django-admin startproject mysite
    
    mysite
    	mysite
      manage.py
  2.启动django项目(先切换到mysite路径下)
  	python3 manage.py runserver 127.0.0.1:9090
  3.创建应用
  	python3 manage.py startapp app01
"""
1.一个django项目就类似于是一个空壳子 本身没有任何的内容(大学)
应用就类似于是一个个的功能模块(学院)

2.创建应用之后一定要先去配置文件中注册才能生效
INSTALLED_APPS = [
	'app01'  # 简写
	‘app01.apps.App01Config’  # 全称
]
"""

# pycharm创建
"""
1.命令行创建不会自动创建templates文件夹并且也不会自动配置路径
	DIR:[os.path.join(BASE_DIR,'templates')]
2.pycharm则会自动创建并且自动配置路径
3.pycharm还可以自动帮你创建一个应用并且自动注册(只能创一个)
"""

"""
django主要文件介绍
	-mysite
		--mysite
			---urls.py
			---settings.py
			...
		-manage.py
		-app01
			--migrations
				数据库迁移记录
			--apps.py
			--tests.py
			--models.py
			--views.py
"""

django小白必会三板斧

点击查看代码
from django.shortcuts import HttpResponse,render,redirect

return HttpResponse('字符串')

return render(request,'login.html')
def ab_render(request):
    # 视图函数必须要接受一个形参request
    user_dict = {'username':'jason','age':18}
    # 第一种传值方式:更加的精确 节省资源
    # return render(request,'01 ab_render.html',{'data':user_dict,'date':123})
    # 第二种传值方式:当你要传的数据特别多的时候
    """locals会将所在的名称空间中所有的名字全部传递给html页面"""
    return render(request,'01 ab_render.html',locals())
	
return redirect(url)

静态文件配置

点击查看代码
"""
在浏览器窗口输入url之所以能够访问到对应的资源是因为后端提前开设了该资源的访问接口

我们习惯将html文件存放在templates文件夹下
我们习惯将静态文件存放在static文件夹下
	静态文件
		网站已经写好的 活着是第三方现成的代码 直接拷贝使用
		css文件	js文件	img文件	第三方组件
	
	static文件夹内还会创建几个文件夹
		css
		js
		img
		第三方
	
	django不会自动帮你创建static文件夹需要你自己手动创建
"""
STATIC_URL = '/static/'  # 访问静态文件的令牌

# 静态文件配置 settings.py
STATICFILES_DIRS = [  # 令牌持有者可以访问的文件路径
  os.path.join(BASE_DIR,'static'),
  os.path.join(BASE_DIR,'static1'),
  os.path.join(BASE_DIR,'static2'),
]
"""
查找顺序就是从上往下依次查找,查找到一个就不会继续往下找了所以可能会出现替换的情况
"""

# 令牌动态解析
<link href="/static/a.txt"></link>	

{% load static %}
<link href="{% static 'a.txt' %}"></link>	

request对象方法

点击查看代码
# 登陆功能

# form表单action三个参数写法

request.method  #	获取当前请求方式  全大写的字符串

request.GET		# 获取url问好后面携带的参数
	.get()  列表最后一个元素
  .getlist()  拿整个列表
request.POST  # 获取post请求提交过来的普通键值对(不包含文件)
	.get()  列表最后一个元素
  .getlist()  拿整个列表
"""
前期我们在朝django后端提交post请求的是时候要先去配置文件中注释一行代码
MIDDLEWARE = [
	# csrf...
]
"""
	
def index(request):
  if request.method == 'POST':
     return HttpResponse('post')
  return HttpResponse('get')

pycharm链接数据库

点击查看代码
# 找到pycharm database选项(三个地方查找)

# 选取对应的数据库 下载对应的驱动
"""
明明链接上了数据库 但是看不到表无法操作
这个时候你只需要将刚刚创建的链接删除 重新链接一次即可
"""

django链接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()

django orm(重要)

点击查看代码
"""
orm不会帮你创建库 只能创建到表的层面
需要你自己提前创建好库
"""
# 对象关系映射
表					类
记录			对象
数据			对象属性/方法
"""
能够让一个不会sql语句的python程序员也能够简单快捷的操作数据库,极大的提升开发效率
"""

# 去应用下的models.py中书写模型类
	# 类			模型类
  # 表			模型表
  class UserInfo(models.Model):
    # 当你没有创建主键字段的时候orm会自动帮你创建一个名为id的主键字段
    uid = models.AutoField(primary_key=True)
    # uid int primary key auto_increment
    username = models.CharField(max_length=32)
    # username varchar(32)	CharField字段一定要书写max_length参数
    password = models.IntegerField()
    # password int
**************************数据库迁移命令*****************************
1.python3 manage.py makemigrations
	# 将操作记录到小本本上(migrations文件夹内)  不能真正的直接操作数据库
2.python3 manage.py migrate
	# 将操作真正的同步到数据库中
"""只要在models中书写了跟数据库相关的代码 就必须要重新执行上述两条命令"""

# pycharm简单快捷输入
	tools
  	run manage.py task
    	自动提示
*******************************************************************

简单的orm语句

点击查看代码
# 字段的增删改查
	# 增
  	1.终端里面自己加默认值
    2.null=True
    3.default='666'
    
  # 删
  	注释代码执行两条命令 (然后收拾行李跑路走人)
    # 在操作models.py中的代码的时候一定要细心
  
  # 改
  	修改代码执行两条命令

# 数据的增查
	# 增
  	from app01 import models
  	1.create()
    	user_obj = models.UserInfo.objects.create(**kwargs)   "这里都是这种写法:models.表名.object.方法"
      # 改方法有一个返回值 就是当前创建的数据对象本身
    2.对象.save()
    	# 先生成一个类对象
      user_obj = models.User(**kwargs)
      # 对象调用save方法
      user_obj.save()
  
  # 查
  	1.filter()							# where
    	res = models.UserInfo.objects.filter(**kwargs)
      """
      返回的结果是一个querySet对象 你可以把它看成是一个列表套数据对象		
      	[数据对象1,数据对象2...]
      
      支持索引和切片操作 但是不支持负数 并且不推荐你使用索引
      
      .first()方法
      
    	filter括号内可以写多个参数 查询的时候默认是and关系
      """

数据的编辑和删除

点击查看代码
# 查询所有数据
    res = models.User.objects.filter()
  res = models.User.objects.all()
# 编辑数据
    """
    1.首先得获取用户想要编辑的数据主键值
            url?edit_id=1
            url/1/
    2.后端查询出对应的数据对象展示到前端
            利用input标签的value属性
    3.提交post请求修改数据
            前期提交post请求一定要先去配置文件中注释点一行(csrf...)
            如果不注释会报403错误
    """
  # 批量更新
    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()
  """
  该方法当字段比较多的时候效率很降低很多
  因为它是从头到尾讲数据所有的字段重新写一遍
  """
# 删除数据
    """
    1.数据并不会真正意义上的删除,我们在创建表的时候会加一个用来标示是否被删除的字段
        is_delete
        is_alive
        is_status
        ...
    删数据其实就是修改字段的状态 之后通过代码筛选出没有删除的状态数据即可
    
    2.删除数据的时候应该有一个二次确认的过程而不应该直接删除
        ajax讲完之后加二次确认结合sweetalaert
    """

图书管理系统表设计(orm创建表关系)

点击查看代码
class User:
  models.ForeignKey(to='Publish')
  models.ForeignKey(to=Publish)  # 报错
  
class Publish:
  pass

"""
一对多
    models.ForeignKey(to='关联表名')  常用
    models.ForeignKey(to=关联表名)      关联表名必须出现在上方(了解即可)
        1.在django1.X版本中外键默认就是级联更新删除的
        2.会自动给字段加_id后缀 无论你有没有加(自己不要自作聪明的加上)
        3.一对多 外键字段建在多的一方
        
一对一
    models.OneToOneField(to='关联表名')
        1.在django1.X版本中外键默认就是级联更新删除的
        2.会自动给字段加_id后缀 无论你有没有加(自己不要自作聪明的加上)
        3.外键建在任意一方均可 但是推荐你建在查询频率较高的表中(orm查询方便)
        
多对多
    models.ManyToManyField(to='关联表名')
        1.在django1.X版本中外键默认就是级联更新删除的
        2.该字段是一个虚拟字段不会真正的在表中展示出来 而是用来告诉Django orm当前表和关联表是多对多的外键关系 需要自动创建第三张关系表
        3.在Django orm中多对多的表关系有好几种(三种)创建方式
        4.外键建在任意一方均可 但是推荐你建在查询频率较高的表中(orm查询方便)
        
判断表关系的方式:换位思考
"""

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
额外扩展:缓存数据库的作用
"""
posted @ 2021-12-09 14:43  maju  阅读(87)  评论(0)    收藏  举报