一、Django静态文件配置

##settings.py##
静态文件配置:
STATIC_URL = '/static/'

# 静态文件配置
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static')
]
# 暴露给外界能够访问服务器静态文件夹下面所有的资源


STATIC_URL = '/xxx/'      # 接口前缀 跟你的静态文件夹的名字一点关系都没有
            # 默认情况下这个前缀跟静态文件夹名字一样!!!

# 静态文件配置
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static'),  # 就是你的静态文件夹路径
    os.path.join(BASE_DIR,'static1'),
    os.path.join(BASE_DIR,'static2')
]

# ps:会依次查找列表中所有的静态文件路径 找到的话立刻停止,都没有找到返回404


静态文件目录结构:
项目目录-->static-->{css, js, images, bootstrap-3.3.7}


<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>


二、form表单提交数据的动作两种方式

<input  type='submit'>
<button></button>


三、form提交数据的地址如何指定及方式

action属性控制提交的地址:
方式:
    1.全路径
        <form action="http://127.0.0.1:8000/login/">
    2.只写路径后缀
        <form action="/login/">
    3.不写 (默认往当前路径提交)

form表单默认是get请求;


四、案例-根据客户端请求方式的不同执行不同的逻辑代码

根据客户端请求方式的不同执行不同的代码:
def login(request):
    print(request.method)   #获取用户提交的请求方式,全是大写的字符串
    if request.method == 'GET':
        return render(request,'login.html') #get的话返回登录页面
    return HttpResponse('ok')   #如果是post的话进行其他操作


def login(request):
# 获取用户端提交的请求方式
print(request.method)  # 拿到的请求方式是全大写的字符串

if request.method == 'POST':
    print(request.POST)  # 你就把它当成一个大字典里面存放了客户端post提交的所有的数据
    # request.POST:< QueryDict: {'username': ['jason'], 'password': ['123']} >
    print(request.POST.get('username'))  # value虽然是个列表但是获取value的时候拿到却是单个元素
    # 默认只会取value列表里面的最后一个元素
    # request.POST:<QueryDict: {'username': ['jason', 'egon'], 'password': ['123']}>
    print(request.POST.getlist('username'))  # 要想一次性获取value列表里面所有的数据需要用getlist()
    # ['jason', 'egon']
    print(request.POST['password'])  # 不推荐使用该方法获取数据
    return HttpResponse('OK')
return render(request,'login.html')

获取value列表里面所有的元素需要使用getlist  应用场景:用户的爱好 多选框;
get只会获取到value列表的最后一个元素;


五、django连接数据库

1、需要修改配置文件

##settings.py##
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day55',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': '123456',
    }
}

ps:键必须都是大写


2.告诉django用pymysql替换它默认mysqldb模块连接数据库

方式1:在你的项目文件夹下面的__init__.py
方式2:也可以在你的应用文件夹下面的__init__.py
写入一下两行:

# 固定写法
import pymysql
pymysql.install_as_MySQLdb()  # 告诉django用pymysql代替mysqldb连接数据库


六、ORM

1、ORM简介

ORM 全拼Object-Relation Mapping.
对象关系映射;

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

django的orm不能够自动创建库,但是可以自动帮你创建表

提示:一个django项目就使用一个库,不要多个django项目使用一个库


2、ORM优缺点

优点:
(1)只需要面向对象编程, 不需要面向数据库编写代码.
    对数据库的操作都转化成对类属性和方法的操作.
    不用编写各种数据库的sql语句.

(2)实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
    不在关注用的是mysql、oracle...等.
    通过简单的配置就可以轻松更换数据库, 而不需要修改代码.


缺点:
相比较直接使用SQL语句操作数据库,有性能损失.
根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.


2、数据库同步

##models.py##

当models.py文件有改动时,就要在项目目录中执行下列两个命令;

python3 manage.py makemigrations  将你的数据库变动记录到一个小本本上(并不会帮你创建表)
python3 manage.py migrate         将你的数据库变动正在同步到数据库中


七、ORM使用

1、字段类型

示例:
class User(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=16)
    addr = models.CharField(max_length=32, default='China')



属性名 = models.字段类型,定义属性时需要指定字段类型, 通过字段类型的参数指定选项

属性名:
    不允许使用python的保留关键字
    不允许使用mysql的保留关键字
    不允许使用连续的下划线,因为Django的查询语法就是连续的下划线

AutoField:自动增长的IntegerField, 不指定时Django会自动创建属性名为id的自动增长属性
BooleanField:布尔字段,值为True或False
NullBooleanField:支持Null、True、False三种值
CharField(max_length=20):字符串
    参数max_length表示最大字符个数

TextFiled:大文本字段,一般超过4000个字符时使用
IntegerField:整数
DecimalField(max_digits=None, decimal_places=None):可以指定精度的十进制浮点数
    参数max_digits表示总位数
    参数decimal_places表示小数位数

FloatField():浮点数  DateField[auto_now=False, auto_now_add=False]):日期
    参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false
    参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false
    参数auto_now_add和auto_now是相互排斥的,组合将会发生错误

TimeField:参数和DateField一样
DateTimeField:日期时间,参数同DateField
FileField:上传文件字段,以二进制的形式
ImageField:继承于FileField,对上传的内容进行校验,确保是有效的图片


2、字段选项

null:如果为True,表示允许为空,默认值是False
blank:如果为True,则该字段允许为空白,默认值是False     对比:null是数据库范畴的概念,blank是表单验证范畴的

db_column:字段的名称,如果未指定,则使用属性的名称(只限于数据库表中的名字,操作数据库还是类属性的名字)
db_index:若值为True, 则在表中会为此字段创建索引,默认值是False(为了优化查询速度 )
default:默认值,这可以是值或可调用对象。如果可调用,则每次创建新对象时都会调用它。
primary_key:若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用
unique:如果为True, 这个字段在表中必须有唯一值,这个值不能重复,默认值是False

关系型字段类型:关联表中使用:
注意:Django会自动为表创建主键字段
    如果使用选项设置某属性为主键字段后,Django不会再创建自动增长的主键字段
    默认创建的主键字段为id,可以使用pk代替,pk全拼为primary key


3、关系字段类型

关系型数据库的关系包括三种类型:
    ForeignKey:一对多,将字段定义在多的一端中
    ManyToManyField:多对多,将字段定义在任意一端中
    OneToOneField:一对一,将字段定义在任意一端中

可以维护递归的关联关系,使用self指定


4、元选项

作用:修改数据库表的默认的名称

数据库表的默认名称为 :
    应用名_模型名
    如:应用名:app01   模型类:User
    则表名为:app01_user


  class BookInfo(models.Model):
      name = models.CharField(max_length=20)   #图书名称

      class Meta: #元信息类
          db_table = 'bookinfo' #自定义表的名字


八、Django数据库的操作

from django.shortcuts import render,HttpResponse,redirect
import pymysql
from app01 import models

# Create your views here.
def login(request):
    # 获取用户端提交的请求方式
    print(request.method)  # 拿到的请求方式是全大写的字符串
    # if request.method == 'GET':
    #     return render(request,'login.html')
    # elif request.method == 'POST':
    #     return HttpResponse("收到了 老弟")
    if request.method == 'POST':
        # print(request.POST)  # 你就把它当成一个大字典里面存放了客户端post提交的所有的数据
        # # request.POST:< QueryDict: {'username': ['jason'], 'password': ['123']} >
        # print(request.POST.get('username'))  # value虽然是个列表但是获取value的时候拿到却是单个元素
        # # 默认只会取value列表里面的最后一个元素
        # print(request.POST.getlist('username'))  # 要想一次性获取value列表里面所有的数据需要用getlist()
        # print(request.POST['password'])  # 不推荐使用该方法获取数据
        # 获取用户输入的用户名和密码
        username = request.POST.get('username')
        password = request.POST.get('password')
        conn = pymysql.connect(
            host='127.0.0.1',
            port = 3306,
            user = 'root',
            password = '123',
            database = 'day54',
            charset = 'utf8',
            autocommit = True
        )
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        cursor.execute('select * from userinfo where name=%s and password=%s',(username,password))
        user_info = cursor.fetchall()
        if user_info:
            return HttpResponse('登录成功')
    # print(request.GET)  # <QueryDict: {'username': ['jason'], 'password': ['123']}>
    # # 获取get请求数据的方式跟post请求完全一样!!!
    return render(request,'login.html')


def reg(request):
    if request.method == 'POST':
        # 获取用户输入的用户名和密码
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 操作数据库user表插入数据
        # 方式1:
        # user_obj = models.User.objects.create(name=username,password=password)
        # 方式2:
        user_obj = models.User(name=username,password=password)
        user_obj.save()  # 对象调用save方法保存到数据库
        print(user_obj.pk)  # pk获取主键字段对应的值  无论的你主键叫什么名字
        print(user_obj.name)  # 获取用户数据的name值
        print(user_obj.password)  # 获取用户数据的password值
        return redirect('/userlist/')
    return render(request,'reg.html')

def userlist(request):
    # 获取数据库数据
    user_list = models.User.objects.all()  # select id,name,password form user;
    # print(user_list.query)  # 只要是QuerySet就可以点query查看获取到当前QuerySet对象的内部sql语句
    # for user_obj in user_list:
    #     print(user_obj.pk,user_obj.name)
    return render(request,'userlist.html',locals())

def delete_user(request):
    # 从get请求携带的参数中获取用户想要删除的数据id
    delete_id = request.GET.get('delete_id')
    # res = models.User.objects.filter(id=1)[0]
    # res = models.User.objects.filter(id=1).first()
    models.User.objects.filter(id=delete_id).delete()  # 会将queryset所有的数据对象全部删除
    # print(res)  # <QuerySet [<User: jason>]>
    # # print(res.query)
    # print(type(res))
    return redirect('/userlist')


def edit(request):
    if request.method == 'POST':
        print(request.POST)
        print(request.GET)
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 获取编辑对象的id方式
        edit_id = request.POST.get('edit_id')

        edit_id = request.GET.get('edit_id')
        # 更新数据库
        models.User.objects.filter(id=edit_id).update(name=username,password=password)
        return redirect('/userlist')
    # 获取用户想要修改的数据的id
    edit_id = request.GET.get('edit_id')
    # 将该数据查询出来渲染到一个编辑页面
    # 查询数据方式1
    user_obj = models.User.objects.filter(id=edit_id).first()
    # 查询数据方式2
    # # user_obj = models.User.objects.get(id=edit_id)
    # print(user_obj,type(user_obj))
    # 将当前数据渲染到一个编辑页面上

    return render(request,'edit.html',locals())


九、a标签href属性

利用a标签href属性 可以指定页面跳转的路径  href可以写全路径 但是推荐写后缀即可:
<a href="/reg/" class="btn btn-success">添加数据</a>
 <a href="/edit/?edit_id={{ user_obj.pk }}" class="btn btn-primary">编辑</a>
 <a href="/delete_user/?delete_id={{ user_obj.pk }}" class="btn btn-danger">删除</a>

# 注意 路径的书写一定要加斜杠


十、表单元素input type=”hidden”

隐藏域在页面中对于用户是不可见的,在表单插入中隐藏域的目的在于收集和发送信息,以利于被处理表单的程序所使用
注:隐藏只是在网页页面上不显示输入框,但是虽然隐藏了,还是具有form传值功能。一般用来传值,而不必让用户看到。

基本语法:
<input type="hidden" name="field_name" value="value" />


<div class="container">
    <div class="row">
        <h1>编辑数据</h1>
        <div class="col-md-6 col-md-offset-3">
            <form action="/edit/?edit_id={{ user_obj.pk }}" method="post">
                <input type="hidden" name="edit_id" value="{{ user_obj.pk }}">
                <p>username:<input type="text" name="username" value="{{ user_obj.name }}" class="form-control"></p>
                <p>password:<input type="text" name="password" value="{{ user_obj.password }}" class="form-control"></p>
                <input type="submit" class="btn btn-warning">
            </form>
        </div>
    </div>
</div>


def edit(request):
    if request.method == 'POST':
        print(request.POST)
        print(request.GET)
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 获取编辑对象的id方式
        edit_id = request.POST.get('edit_id')

        edit_id = request.GET.get('edit_id')
        # 更新数据库
        models.User.objects.filter(id=edit_id).update(name=username,password=password)
        return redirect('/userlist')
    # 获取用户想要修改的数据的id
    edit_id = request.GET.get('edit_id')
    # 将该数据查询出来渲染到一个编辑页面
    # 查询数据方式1
    user_obj = models.User.objects.filter(id=edit_id).first()
    # 查询数据方式2
    # # user_obj = models.User.objects.get(id=edit_id)
    # print(user_obj,type(user_obj))
    # 将当前数据渲染到一个编辑页面上

    return render(request,'edit.html',locals())
01-03 14:10