Django 基础学习笔记二

  1. Django 开发
    一:基础
    1.创建项目目录:
    django-admin startproject bysms
    bysms/   --- 项目根目录
        manage.py --工具脚本,用于管理项目
        bysms/ --python包,名称创建后不可更改,manege.py 会用到
             __init__.py --包
              settings.py ---项目配置文件
              urls.py -- 总路由,转发请求
              wsgi.py --web服务网关接口,由wsgi web server 和wsgi web application 组成,web server(提供高效的http请求处理环境,多线程,多进程、协程的机制) 接受前端的请求后会调用wsgi web application(业务逻辑控制)
     
    2.运行Django web服务
    在项目根目录:python manage.py runserver 0.0.0.0:80    --启动服务,即可用浏览器访问127.0.0.1 即可访问web 服务
    --0.0.0.0:80 web 服务绑定的ip 和端口,绑定本机所有的地址
     
    3.创建项目app
    python manage.py startapp sales
    创建一个目录名为 sales, 对应 一个名为 sales 的app,里面包含了如下自动生成的文件
     
    sales/
         __init__.py
         admin.py apps.py
         migrations/
              __init__.py
         models.py
         tests.py
         views.py --- 处理http 请求的代码
    4.创建子路由
    主路由中import include
    增加一条路由,通过include 转发到子路由,需要在app中创建 urls.py 文件
     
    from django.contrib import admin
    from django.urls import path,include
    from sales.views import listorders
     
    urlpatterns = [
    path('admin/', admin.site.urls),
    # 添加如下的路由记录
    path('sales/', include('sales.urls')),
    ]
    app中的urls.py
    import处理路由逻辑的类 views.py
    增加一条路由,有没有斜线要看具体的接口文档,与主路由拼接成完整的路由,调用views 中的函数来处理不同的请求
    from django.urls import path
    from . import views
     
    urlpatterns = [
    # 添加如下的路由记录
    path('orders/', views.listorders),
    ]
     
     
    5.创建数据库和表
    项目中数据库的配置在 mybysms/settings.py,默认的数据库sqlite3
    python manage.py migrate -- 在根目录下生成 db.sqlite3 的数据库
    创建 Djiango 必须的基本表
    mysql
    启动mysql 服务
    netstart mysql
    终止服务
    netstop mysql
    连接数据库服务器
    mysql -uroot -phuawei@1234
    创建数据库
    create database Gp1Day15 charset=utf8;
    安装驱动
    import pymysql
    pymysql.install_as_MySQLdb()
     
    执行数据迁移
    python manage.py migrate
     
    auth_group  : id name
    auth_group_permissions
    auth_permission
    auth_user
    auth_user_groups
    auth_user_user_permissions
    django_admin_log
    django_content_type
    django_migrations
    django_session
     
    6.什么是ORM
    通常,在Django中
    • 定义一张数据库的表 就是定义一个继承自 django.db.models.Model 的类
    • 定义该表中的字段(列), 就是定义该类里面的一些属性
    • 类的方法就是对该表中数据的处理方法,包括 数据的增删改查
    这样,开发者对数据库的访问,从原来的使用底层的 sql 语句,变成 面向对象的开发,通过一系列对象的类定义 和方法调用就可以 操作数据库。
    这种 通过 对象 操作数据库 的方法 被称之为 ORM (object relational mapping),下面我们就来看怎样使用。
     
    7.定义数据库表
    python manage.py startapp common
    打开 common/models.py,导入 models ,继承models.Model,实际生成的表名为app名.类名(小写):common_custormer  models.CharField 创建字符型( varchar)的属性
    from django.db import models
     
    class Customer(models.Model):
    # 客户名称
       name = models.CharField(max_length=200)
     
    # 联系电话
       phonenumber = models.CharField(max_length=200)
     
    # 地址
       address = models.CharField(max_length=200)
     
    在models.py 中创建好表的属性,在settiing 文件中 install_apps 中加入 ‘common.apps.CommonConfig’
    告诉Django CommonConfig 是common/apps.py文件中定义的一个应用配置的类。
     
    python manage.py makemigrations common ---告诉Django common app 的models.py 已经被修改了,生成数据库操作代码0001_initial.py 文件
    python manage.py migrate   -- 执行0001_initial.py 代码,操作数据库,创建表
     
    二:Django Admin管理数据
    Django 提供了一个管理员界面可以方便操作数据库
    1.创建超级管理员
    python manage.py createsupperuser
    2.在common/Admin.py 中添加    注册我们定义的model类
     
    from django.contrib import admin
     
    from .models import Customer
     
    admin.site.register(Customer)
     
    管理视图:
    三:读取数据库
    1.在sales 中导入customer,定义一个listcustomers 函数,  data=Customer.objects.values() 返回一个 QuerySet 对象 ,包含所有的表记录,对data 进行遍历,拼接成需要返回的字符串格式,调用HttpResponse(restr)
    def listcustomers(request):
    # 返回一个 QuerySet 对象 ,包含所有的表记录
    # 每条表记录都是是一个dict对象,
    # key 是字段名,value 是 字段值
    qs = Customer.objects.values()
     
    # 定义返回字符串
    retStr = ''
    for customer in qs:
    for name,value in customer.items():
    retStr += f'{name} : {value} | '
     
    # <br> 表示换行
    retStr += '<br>'
    return HttpResponse(retStr)
     
     
    2.条件过滤,当用户在浏览器输入 /sales/customers/?phonenumber=13000000001 
    request.GTE-->字典对象
    对customer 表中的数据进行过滤,使用filter
    def listcustomers(request):
    # 返回一个 QuerySet 对象 ,包含所有的表记录
    qs = Customer.objects.values()
     
    # 检查url中是否有参数phonenumber
    ph = request.GET.get('phonenumber',None)
     
    # 如果有,添加过滤条件
    if ph:
    qs = qs.filter(phonenumber=ph)
     
    # 定义返回字符串
    retStr = ''
    for customer in qs:
    for name,value in customer.items():
    retStr += f'{name} : {value} | '
    # <br> 表示换行
    retStr += '<br>'
     
    return HttpResponse(retStr)
     
    filter 的过滤条件可以有多个
    qs = qs.filter(phonenumber=ph,address='安徽芜湖')
     
     
    四:对资源进行增删改查处理
    1.Django 的 url路由功能 不支持 根据 HTTP 请求的方法 和请求体里面的参数 进行路由,
    自己编写一个函数, 来 根据 http请求的类型 和请求体里面的参数 分发(或者说路由)给 不同的函数进行处理。
     
    def dispatcher(request):
    # 将请求参数统一放入request 的 params 属性中,方便后续处理
     
    # GET请求 参数在url中,同过request 对象的 GET属性获取
    if request.method == 'GET':
    request.params = request.GET
     
    # POST/PUT/DELETE 请求 参数 从 request 对象的 body 属性中获取
    elif request.method in ['POST','PUT','DELETE']:
    # 根据接口,POST/PUT/DELETE 请求的消息体都是 json格式
    request.params = json.loads(request.body)
     
     
    # 根据不同的action分派给不同的函数进行处理
    action = request.params['action']
    if action == 'list_customer':
    return listcustomers(request)
    elif action == 'add_customer':
    return addcustomer(request)
    elif action == 'modify_customer':
    return modifycustomer(request)
    elif action == 'del_customer':
    return deletecustomer(request)
     
    else:
    return JsonResponse({'ret': 1, 'msg': '不支持该类型http请求'})
    2.测试后端代码
    import requests,pprint
    pprint.pprint(response.json())
     
    五:登录
     
    1.session和token 
    session:
    用户登录成功后, 服务端就在数据库session表中 中创建一条记录,记录这次会话
    服务端将 用户的信息数据 + 密钥 一起进行一个哈希计算, 得到一个哈希值
    request.session['usertype'] = 'mgr'
    将用户的类型保存在session 数据中
    Django 框架会自动在HTTP响应头中加入类似下面的sessionid  cookie
    然后在该登录请求的HTTP响应消息中, 的头字段 Set-Cookie 里填入 sessionid 数据。
    Set-Cookie: sessionid=???????? 后面的请求会带上这个 sessionid
    判断是否登录
    if 'usertype' not in request.session
    判断是否为管理员
    request.session['usertype'] != 'mgr'
    session 机制性能问题
    验证请求是根据sessionid 到数据库中查找session表的,而数据库操作是服务端常见的性能瓶颈,尤其是当用户量比较大的时候
    session 机制扩展性问题
    当系统用户特别多的时候,后端处理请求的服务端通常由多个,部署在多个节点上。 但是多个节点都要访问session表,这样就要求数据库服务能够被多个节点访问,不方便切分数据库以提高性能
     
     
    2.Token 机制
    就是包含了 数据信息 和 校验信息的 数据包。
     token机制 数据信息 直接传给 客户端,客户每次请求再携带过来给服务端。服务端无需查找数据库,直接根据token里面的数据信息进行校验
    服务端配置一个密钥(secret key),该密钥是服务端私密保存的,不能外泄
    在用户登录成功后, 服务端将 用户的信息数据 + 密钥 一起进行一个哈希计算, 得到一个哈希值
    大家可以发现 token 里面 包含了用户数据信息 和 用于校验完整性的哈希值。
     
    如果客户修改了数据信息, 因为他不知道密钥,没法得到正确的新的哈希值,那么 服务端根据 篡改后的数据+密钥 得到的新 哈希值一定和 保存在token中的老哈希值 不同。
     
    六:数据库
    mysql、oracle、 sqlserver、SQLite 都是关系型数据库,而 mongodb、Cassandra不是
    常见的3种关联关系就是: 一对多 , 一对一 , 多对多
     
    1.一对多:
    jango中定义外键 的方法就是 Model类的该属性字段 值为 ForeignKey 对象
    表之间 一对多 的关系,就是 外键 关联关系
    class Order(models.Model):
    # 订单名
    name = models.CharField(max_length=200,null=True,blank=True)
     
    # 创建日期
    create_date = models.DateTimeField(default=datetime.datetime.now)
     
    # 客户
    customer = models.ForeignKey(Customer,on_delete=models.PROTECT)
     
    on_delete :
    1) CASCADE: 删除主键记录和 相应的外键表记录。
    2) PROTECT: 禁止删除记录。
    3) SET_NULL: 删除主键记录,并且将外键记录中外键字段的值置为null。 当然前提是外键字段要设置为值允许是null
     
    2.一对一
    Django 中 用 OneToOneField 对象 实现 一对一 的关系,如下
    Django发现这样一对一定定义,它会在migrate的时候,在数据库中定义该字段为外键的同时, 加上unique=True 约束,
    表示在此表中,所有记录的该字段 取值必须唯一,不能重复
     
    class Student(models.Model):
    # 姓名
    name = models.CharField(max_length=200)
    # 班级
    classname = models.CharField(max_length=200)
    # 描述
    desc = models.CharField(max_length=200)
     
     
    class ContactAddress(models.Model):
    # 一对一 对应学生
    student = models.OneToOneField(Student, on_delete=models.PROTECT)
    # 家庭
    homeaddress = models.CharField(max_length=200)
    # 电话号码
    phone = models.CharField(max_length=200)
     
    3.多对多
     
    Django是通过 ManyToManyField 对象 表示 多对多的关系的。
    # 订单购买的药品,和Medicine表是多对多 的关系
    medicines = models.ManyToManyField(Medicine, through='OrderMedicine')
     
    案例:
    创建两张表,学生表中存在一对多的外键
     
    Django shell
    python manage.py shell 进入shell 环境
    输入数据,创建数据
    通过对象访问外键表
    s1 = Student.objects.get(name='白月')
    s1.country.name
    根据外键表
    查找Student表中所有 一年级中国 学生
    Student.objects.filter(grade=1,country__name='中国').values()
    Student.objects.filter(grade=1,country__name='中国')\ .values('name','country__name')
    country__name为双下划线
     
     
    使用 annotate 方法将获取的字段值进行重命名
     
     
     
    反向访问
    通过 表Model名转化为小写 ,后面加上一个 _set 来获取所有的反向外键关联对象
    cn = Country.objects.get(name='中国')
    cn.student_set.all()
     
    Django还给出了一个方法,可以更直观的反映 关联关系, 在定义Model的时候,外键字段使用 related_name 参数
     
     
     
     
    cn = Country.objects.get(name='中国')
    cn.students.all()
     
    反向过滤:
    使用了反向关联名字
    Country.objects.filter(students__grade=1).values()
    没有指定方向关联名, 则应该使用 表名转化为小写 
    Country.objects.filter(student__grade=1).values() .distinct()
     
     
    使用 Django 的 with transaction.atomic(),将一批数据库操作放在事务中,任何一次数据库操作失败了,数据库系统会让整个事务回滚
     
    七: 分页 和 过滤 
    1.分页
    前端发送的请求中需要携带 两个信息: 每页包含多少条记录 和 需要获取第几页
    我们定义列出数据请求中 添加 2个url 参数: pagesize 和 pagenum 分别对应这两个信息
     
    创建了 分页对象,在初始化参数里面设定每页多少条记录
    pgnt = Paginator(qs, pagesize) 返回的 分页对象 赋值给变量 pgnt。
    一页的数据 就可以通过 pgnt.page(pagenum) 获取
    总共有多少页,通过 pgnt.count 得到。
     
     
    2.过滤
    ”且“
    qs.filter(name__contains='乳酸')
    qs.filter(name__contains='乳酸').filter(name__contains='注射液')
    qs.filter( Q(name__contains='乳酸') & Q(name__contains='注射液'))
    --> WHERE name LIKE '%乳酸%' AND name LIKE '%注射液%'
    “或”
    from django.db.models import Q
    qs.filter(Q(name__contains='乳酸'))
    qs.filter( Q(name__contains='乳酸') | Q(name__contains='注射液'))
    --> WHERE name LIKE '%乳酸%' OR name LIKE '%注射液%'
     
     
     
    生产环境框架
     
     
     
    修改 ./bysms/settings.py
     
     
     
    生产环境,我们使用 Gunicorn 作为 Django的WSGI前端,首先我们需要创建一个 Gunicorn启动配置文件 ./bysms/gunicorn_conf.py 
    启动Django 后端服务器
     
     
    八:安装、配置 Nginx
    大家首先以root 用户 登录 CentOS 主机,按照下面的步骤安装Nginx
    • 先执行命令 yum install gcc 确保gcc编译器安装好
    • 先 安装Nginx依赖包 ,执行命令 yum -y install pcre-devel openssl openssl-devel
    • 下载、编译、安装 Nginx
      执行命令 wget http://nginx.org/download/nginx-1.15.5.tar.gz 下载Nginx代码包;
      执行命令 tar zxvf nginx-1.15.5.tar.gz 解压 代码包
      执行命令 cd nginx-1.15.5 进入到代码目录
      执行命令 ./configure --prefix=/usr/local/nginx --with-http_ssl_module 配置编译安装选项
      执行命令 make && make install 编译安装
    Nginx的配置文件路径是:/usr/local/nginx/conf/nginx.conf

    启动 Nginx

    启动Nginx,必须以root用户执行。
    执行命令 /usr/local/nginx/sbin/nginx ,即可启动Nginx服务。
     
    如果启动报错,你需要查看日志文件,可以打开 /usr/local/nginx/logs/error.log 查看错误日志文件。
     
    如果你修改了配置文件,需要重启Nginx,可以执行如下命令
    /usr/local/nginx/sbin/nginx -s reload
     
    如果需要关闭Nginx服务,可以执行如下命令
    /usr/local/nginx/sbin/nginx -s stop
     
     
    CREATE USER 'byhy'@'localhost' IDENTIFIED BY 'Mima123$';
    GRANT ALL ON *.* TO 'byhy'@'localhost';
    予byhy 用户所有权限,就是可以 该DBMS系统上 访问所有数据库里面所有的表
     
     
    九:Linux 上安装 Redis
    安装redis
    tar xzf redis-5.0.6.tar.gz
    cd redis-5.0.6
    make 
    make test 
    make install
    接下来执行配置 和 启动 Redis 服务的命令
    cd utils/ ; ./install_server.sh
    Redis 服务就会启动监听在默认端口6379上
     
    和 MySQL 一样,Redis 里面也包含了多个数据库,以数字进行编号,缺省连接是编号为 0 的数据库。
    可以使用命令 select 来选择使用哪个Redis数据库,
    比如下面的命令就选择编号为1的数据库
    > select 1
    OK
    127.0.0.1:6379[1]>
    比如,要为id 为2000 的用户存入等级值 33
    127.0.0.1:6379> set user:2000 33
    要从Redis获取key为 user:2000 的值
    127.0.0.1:6379> get user:2000
     
    查询以 med 开头的key, 使用通配符 *
    keys med*
     
    如果要删除一个key和其对应的对象
    del user:2001
     
    存入Hashes,就使用客户端命令 hmset 或者 hset ,
     hmset 是存入多个字段值
    hmset user:2001 level 10 coin 1977 name 白月黑羽
    只要存入(或者修改)一个字段值,就用可以使用hset, 比如要修改 coin的值为 2000,
    hset user:2001 coin 2000
    > hget user:2001 coin
    "2000"
     
     
    就是把 整个用户表 都直接放入 一个hash 里面
    可以给这个hash对应的对象 起一个key名为 usertable 。
     
    > hmset usertable u2001 id:2001|level:10|coin:1977|name:白月黑羽1 > hmset usertable u2002 id:2002|level:13|coin:1927|name:白月黑羽2
    > hget usertable u2002 "id:2002|level:13|coin:1927|name:\xe7\x99\xbd\xe6\x9c\x88\xe9\xbb\x91\xe7\xbe\xbd2"
    Django项目缓存配置
    pip install django-redis
    然后在 Django 的项目配置文件 settings.py 中,添加如下的缓存配置项
    CACHES = {
    "default": {
    "BACKEND": "django_redis.cache.RedisCache",
    "OPTIONS": {
    "CLIENT_CLASS": "django_redis.client.DefaultClient",
    }
    }
    }应该符合如下两条规则:
    • 频繁读取的数据
      否则使用缓存,性能提升也不大
    • 较少变动的数据
     
     
posted @ 2021-10-13 20:58  Nancyfeng  阅读(152)  评论(0编辑  收藏  举报