Django(Web应用,Django框架)

Web应用的简介

Web应用程序是什么?

  Web应用程序是一种可以通过Web访问的应用程序,也就是说只需要一个浏览器即可,不需要其他软件了。

应用程序有两种模式:C/S、B/S

Django就是开发的B/S应用程序,所以,我们就认为浏览器就是我们的客户端,Django框架就是服务端。

Web应用程序的优点:

  1. 只需要一个浏览器即可,不再需要安装其他的应用软件。

  2. 节省用户的资源空间

  3. 它们不需要更新,是因为服务端只要一更新版本,会直接影响客户端的更新

  4. 跨平台使用

Web应用程序的缺点:

  一旦Web应用程序的服务端宕机,直接影响客户端的正常访问!!!

Web框架:

  框架的意思就是别人提前写好的,我们只需要按照人家的要求在固定的位置写好固定的代码。

手撸Web框架

推导框架的演变,代码无需掌握,重点看思路。

Web应用程序主要就是B/S架构的,浏览器就是客户端,只要现在开发出一个服务端即可。

HTTP协议的相关知识:

四大特性:

  基于请求和响应

  基于TCP协议之上的应用层协议

  无状态

  短连接/长连接

请求数据格式:

  请求首行(请求方式、协议版本号)

  请求头

  /r/n

  请求体

响应数据格式:

  响应首行(响应状态码)

  响应头

  /r/n

  响应体

响应状态码:

1xx 、2xx 、3xx 、4xx 、5xx

 

当我们手写Web框架会出现这种页面,是因为服务端发送的数据不符合HTTP协议规定的格式

 

 代码:服务端

复制代码
import socket
sever = socket.socket()
sever.bind(('127.0.0.1',8000))
sever.listen(3)
print('开始接收数据')
while True:
    conn,addr = sever.accept()
    data = conn.recv(1024)
    print(data.decode('utf8'))
    # 使用流式协议规范发送的数据格式
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    conn.send(b'hello')
    conn.close()
复制代码

结果:

网页显示:

 问题:怎样做到在浏览器的地址栏中写什么就显示什么?

思路:

  1. 在后端肯定是要知道我们在浏览器输入了什后缀

  2. 进行判断,判断是什么后缀就返回什么

浏览器每次朝后端发起请求的时候,都会多一次:/favicon.ico(图标地址),可以先忽略。

 

存在的问题:
1. socket部分我们每次都要书写(要写重复代码)
2. 我们需要自己来处理HTTP格式的数据,自己做切分,自己来取值等比较麻烦
3. 并发问题没有解决

借助于wsgiref模块(内置模块,直接使用)

from wsgiref.simple_server import make_server

解决了socket部分,不需要我们自己写了,在wsgiref模块里人家帮我们写了。

它解决了并发问题WSGIServer类------>wsgiref------>它能够解决的并发量不高----->本地使用wsgiref服务器--------------->代码上线之后,就不是有它----------->uwsgi服务器(它支持的并发量更高)

代码上线之后会使用 Nginx + uwsgi

代码:

复制代码
from wsgiref.simple_server import make_server
def run(env,response):
    # env:类似于request,客户端每次发起请求的时候,所携带的数据都在这个里
    # response:后端给浏览器返回的数据
    print(env) # 将HTTP格式的数据都封装到了大字典里去了
    response("200 OK",[])
    current_path = env.get('PATH_INFO')
    # 进行判断
    if current_path == '/index':
        return [b'index'] # return: 返回给浏览器查看的
    elif current_path == '/login':
        return [b'login']
    else:
        return [b'404 error']
if __name__ == '__main__':
    server = make_server(host='127.0.0.1',port=8000,app=run) #run是个函数名(在django中用的就是函数名)
    #  app=run:只要有客户度发过去请求,那么就会把处理的请求交给run这个函数来处理
    #启动服务端
    server.serve_forever()
复制代码

结果:

改进版:

 

"""
views.py----------------->视图文件--------->主要就是写后端的逻辑的
urls.py------------------>路由文件(后缀)---------->路由与视图函数的对应关系
templates---------------->专门用来存储html文件的
"""

  以后我们要想增加一个后缀,只需要在urls.py中写一个路由和在views.py中写一个视图函数即可。

Django框架的学习

Django是python中使用最多的一个主流框架

python中的主流框架:

Django:

  主要用来开发Web项目的,比较笨重,一般小型项目不怎么使用它,大而全

flask:

  是一个比较轻量级的框架,主要依赖于第三方的模块,不断的安装第三方模块,小而精。

tornado:

  异步非阻塞,比较擅长解决高并发问题

版本问题:

  1.X(老项目) 2.X(新项目) 3.X(新版本),1.x和2.x本质上差别不是很大,但是也有区别。

在drf中,都要使用2.x以上版本,drf这个框架要求Django的版本必须2.x以上

注意事项:

  1. 你的项目名称和应用名称以及其他文件的名称都要使用英文的,坚决不能够使用中文的

  2. 你的计算机名称最后都使用英文的

  3. 一个pycharm窗口只打开一个django项目,不能够一个窗口打开很多个django项目

如何使用Django:

1. 安装Django

pip install Django == 1.11

Django的版本要和解释器的版本要匹配:

  Django2.x版本------------>解释器的版本最好3.6以上

如何验证Django是否安装成功:

  在cmd中输入:django-admin。如果有输出内容就说明安装成功

创建项目:

  1. 命令行创建:

  可以先切换路径,切换到你想把Django项目放到的路径里

  命令:django-admin startproject 项目名

  2. pycharm创建

  File下的New Project 中的django

 命令行与pycharm创建的区别:

 命令行创建不会自动有templatew文件夹,需要自己手动创建而pycharm会自动创建并且还会自动在配置文件中配置对应的路径。也就意味着用命令行创建Django项目的不单单要创建templates文件夹还需要去配置文件中配置路径。 

启动项目:

  1. 命令行启动(cmd)

  先把路径切到manage.py文件所在路径,然后再输入:python36 manage.py runserver 

如图:

 

  项目启动起来之后,会监听:http://127.0.0.1:8000/

  默认端口号是:8000

  如何修改端口号:python36 manage.py runserver 127.0.0.1 8001

  2. pycharm启动:点击启动按钮

  访问项目:http://127.0.0.1:8000/

结果:

创建应用:

  1. 命令行创建

    python manage.py startapp [app_label]

    python manage.py startspp app01

  2. pycharm 创建

当把应用创建出来之后,紧接着要做的一件事情就是:注册应用

在配置文件中注册应用,这个应用才生效

复制代码
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',  # 全称
    'app01',  # 简称
]
复制代码

 

主要文件介绍

myfirst_dj      # 项目名称

  app01      # 应用名称

    migrations   # 这个是用来存储数据库迁移记录

    __init__.py  

    admin.py   # 和后台项目注册等相关

    apps.py    # 跟一些注册有关

    models.py      # 跟数据库打交道的 模型层----->MTV模型

    tests.py    # 测试文件

    views.py    # 视图文件,写一些后端逻辑

  myfirst_dj     

    __init__.py

    settings.py    # 配置文件相关的

    urls.py      # 路由相关的

    wsgi.py   # 内部封装的wsgiref服务器,uwsgi服务器之后,这个文件就没用

    db.sqlite3  # Django自带的小型数据库

  manage.py    # Django框架的入口文件

如图所示:

 

应用

Django主要开发的就是一款Web应用

Django框架类似于是一所大学(空壳子)

应用就是大学里面的二级学院(具备独立的功能模块)

一个应用就是一个独立的功能模块

比如:应用名一定要见名知意

user

order

address

cart...

小白必会三板斧

The view app01.views.index didn't return an HttpResponse object. It returned None instead.

return HttpResponse("OK")  # 返回字符串的
return render(request, 'index.html')  # 返回html文件的
return redirect('http://www.baidu.com') # 重定向
复制代码
###############################自己创建的templates文件夹,要在配置文件注册################
TEMPLATES = [
    {
        'BACKEND':
 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], 
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
        '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',            ],
        },
    },
]
###############################自己创建的templates文件夹,要在配置文件注册################
复制代码

 端口后面要加路由,箭头所指的是我们已经设置好的路由,只有加了明确的路由才会去访问该路由所对应的内容

代码截图:

 

 HttpResponse:返回字符串类型的数据

eg:

  return HttpResponse("你好!")

render:返回html页面

eg:

  return render(request,'myfirst.html')

 redirect:重定向

eg:

  return redirect('http://www.baidu.com') # 重定向:跳转到指定的页面

 

 配置文件的介绍

在settings.py文件中:

  1. 注册应用:

   2.中间件:

  红色框中的那句代码在Django连接数据库时需要注释掉,不然会报错。

   3.根路由文件名:

  4. Django连接MySQL数据库:

   5. 访问静态文件的令牌:此处的static只是一个路径开头

 

静态文件的配置

以登录功能为例:

1. 先在urls文件中,添加登录路由与视图函数中登录函数的对应关系

 2.在views文件中,编写登录函数,渲染登录页面

<form action="">

action参数的三种情况:

  1. 什么都不写,就是朝当前地址提交数据

  2. 要么全写:http://127.0.0.1:8000/login/?username=&password=

  3. 只写后缀:http://127.0.0.1:8000/login/

初步的登录结果如图:

4. 接下来就是要向后端提交数据,要用POST请求方式,但是默认请求方式是GET,如下图所示:

 点击链接会出现下面页面,是因为中间件中有一个文件需要注释掉(为了安全会报错)

需要注释掉,页面就不会报错了。

 

 

 

我们将html文件默认都放在templates文件夹下

我们将网站所使用的静态文件默认放在static文件夹下,需要手动创建这个文件夹。

静态文件:

  网站使用的css文件

  网站使用的js文件

  网站使用的图片

  网站使用的第三方库文件(jQuery、Bootstrap等)

我们还可以针对不同的功能对static文件夹里面的文件进行拆分

可以拆分为:

  css

  js

  img

  ...

当我们导入内部的html页面样式文件时会出现,导入的样式文件并没有生效

 

 文件路径并没有被找到,所以出现404错误

http://127.0.0.1:8000/static/bootstrap-3.4.1-dist/css/bootstrap.min.css,看起来是对的,该地址并没有被访问到。

# 你之前访问的地址都可以访问到,那是因为你在后端开设了可以访问的接口(路由)

# 之所以你现在访问不到刚才的地址,是因为你在后端没有开设这样的一个可访问的接口(路由)

# Django自动的帮我们写好了这样的接口

# 访问静态文件的令牌,以后你只要访问静态文件的路径,就要以/static/开头

需要做下面的修改:(静态文件)

在login.html文件中:将/前面的..去掉,要以/static开头

 在settings.py文件中:需要添加STATICFILES_DIRS文件路径

各个static的关系如下图

 动态文件分析:{% %}里面写路径

配置文件中:

结果如图:

 

request对象请求方法

 request.method  # 请求方式 GET POST
print(request.POST) # <QueryDict: {'username': ['jason'], 'password': ['123']}>
print(request.POST.get('username'))  # jason
print(request.GET)  # <QueryDict: {'username': ['jason'], 'password': ['123']}>
print(request.GET.get('username'))  # jason

例子:

结果如图:

pycharm连接数据库

pycharm它也支持连接数据,Navicat连接数据库,大多数都是使用Navicat。

 

Django连接MySQL

默认情况下:

 连接数据库:

 

连接MySQL数据的时候可能报错的解决办法:

解决bug的思路:
  1. 就是print()
  2. 看是否有日志
  3. 看报错的信息去百度中搜索
  4. 问问别人

1. 如果解释器版本导致的问题,直接改源码

def get_new_connection(self, conn_params):
    conn = Database.connect(**conn_params)
    conn.encoders[SafeText] = conn.encoders[six.text_type]
    # 先判断bytes是否存在于编码器中,如果在才执行操作
    if bytes in conn.encoders: # 加上这句话
        conn.encoders[SafeBytes] = conn.encoders[bytes]
    return conn

2. 解释器版本改为3.6的时候也会报错

Django的底层默认使用的是mysqldb模块,这个模块兼容性很差
# 我们还使用pymysql连接mysql,你要提前安装pymysql模块
报错信息:

 解决方法:在项目的任意的__init__.py中加下面两行代码

import pymysql
pymysql.install_as_MySQLdb()  # 猴子补丁# 这两行代码的意思就是把底层的mysqldb模块换成pymysql

3. 除了使用mysqldb、pymysql之外还可以使用mysqlclient这个模块

你用了mysqlclient这个模块,就不用加上面那两句话了

 mysqlclient安装的时候可能会报各种错误

Django中的ORM

ORM:对象映射模型

以后在Django中写根数据库相关的代码时候,就不用再写原生的SQL语句了,直接通过python代码来操作数据的增删改查。

orm的书写位置:在models.py中书写

概念:
  表 >>>>> 类名

  记录 >>>>> 对象

  字段 >>>>> 属性

创建一张表:

复制代码
from django.db import models

# Create your models here.
# 所有的类必须继承models.Model
class User(models.Model): # 类名
    # 在MySQL中: id int primary key auto_increment
    id = models.AutoField(primary_key=True)
    # username varchar(64)
    username = models.CharField(max_length=64)
    # password varchar(64)
    password = models.CharField(max_length=64)
复制代码

如图所示:

 类写完之后,一定要做数据库迁移,真正的在数据库中生成表:

python36 manage.py makemigrations    # 它的作用是把数据库的迁移记录保存下来
python36 manage.py migrate     # 才是真正的把数据表创建出来

如果前面有表已经创建了主键字段叫id,那么后面的表可以不用再创建id,也能生成id主键,但是要是要想设定aid为主键,就要自己在创建的表中设定

如图所示:

 

ORM增删改查字段

1如何做查询 select * from author where username = jack and password = 123

objects:小组件,里面封装了很多的方法

 res=models.Author.objects.filter(name=username, password=password).all() # 是and查询

res=models.Author.objects.filter(name=username, password=password) # 是and查询

res=models.Author.objects.filter(name=username).filter(password=password)# 是and查询

res=models.Author.objects.filter(name=username, password=password).first() # 是and查询

res=models.Author.objects.create(name=username,password=password)

print(res) # <QuerySet [<Author: Author object>]> QuerySet对象以后可以点出来很多的方法

print(res) # Author object QuerySet对象以后可以点出来很多的方法

 

ORM的增删改成方法

1.查询

  res=models.表名(类名).objects.all()[0]
  res=models.表名(类名).objects.filter(username=username, password=password).all()

  res = models.表名(类名).objects.first()  # 去一条数据 # 判断,内部判断数据是否有,有人家在取0


  # res如果查询出来的是一条,直接就是对象
  # res它查询来的是多条,结果就是queryset对象 [对象,对象,对象]
  # 如果你使用的all查询的,就算查询一条数据,结果也是queryset对象 [对象,对象,对象]
  # 我们直接可以对queryset对象进行循环遍历

2. 增加

第一种方式:

  res=models.表名(类名).objects.create(username='', password='')
  '''增加数据的时候也有返回结果:就是当前插入成功的数据对象''' # 可不是影响的行数
  res.username
  res.password
第二种方式:
  obj = models.表名(类名)(username='', password='')
  obj.save()

3. 更新

第一种方式:

  res=models.表名(类名).objects.update(username='', password='') # 全表更新
  res=models.表名(类名).objects.filter().update(username='', password='')
  '''返回的结果才是影响的行数'''
 第二种方式:
  # 先查询
  user_obj = models.表名(类名).objects.first()
  user_obj.username = username
  user_obj.save()

4. 删除

  models.表名(类名).objects.filter().delete() # 直接就删除了
  """删除的方式有两种类型"""
  1. 物理删除:直接把数据从磁盘中删除,.delete()方式就是直接物理删除
  2. 软删除: 软删除的意思是,不直接从硬盘中删数据,而是在表中在增加一个字段,一般叫is_delete
  它的用法就是,正常的数据这个字段的值为0,如果你要删除这条记录,is_delete=1
  # 每次删除的时候,只需要更新这个字段就可以了

软删除案例:

 # 查询的时候怎么区分是正常数据还是已经被删除的数据?

models.表名(类名).objects.filter(is_delete=1).all()  # is_delete=1:排除了被删除的数据

  

 

posted @   Maverick-Lucky  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示