以登录功能为例:

如果我们用在templates写了一个登录功能的页面,并且想使用样式,但是不能用cdn的形式,那么我们只能将bootstrap,以及jQuery的文件下到本地,不过在Django的项目中怎么导入呢?

下面一步步介绍:

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

静态文件
    前端已经写好了的 能够直接调用使用的文件
        网站写好的js文件
        网站写好的css文件
        网站用到的图片文件
        第三方前端框架
        ...
        拿来就可以直接使用的
"""

注意:

# django默认是不会自动帮你创建static文件夹 需要你自己手动创建
一般情况下我们在static文件夹内还会做进一步的划分处理
    -static      --bootstrap
      --js
      --css
      --img
    其他第三方文件
"""
在浏览器中输入url能够看到对应的资源
是因为后端提前开设了该资源的借口
如果访问不到资源 说明后端没有开设该资源的借口
"""

准备

1、新建static文件夹,并下载好的bootstrap和jQuery按照之前的教程下载并放到static文件夹中(或者是其他的静态文件)

静态文件配置

在项目配置文件settings.py中配置静态文件

方法一:在项目配置文件settings.py配置静态文件

settings.py

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'      # 类似于访问静态文件的令牌,如果想要访问静态文件,就必须以static开头,我们约定俗成是static,令牌也可以不是static,看项目需求

#静态文件配置,符合上面令牌之后,才会匹配下面列表里的路径
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static"),   # 列表说明可以有多个
    os.path.join(BASE_DIR,"static1"),
    os.path.join(BASE_DIR,"static2"),
]

ps:路径问题举例:

#例如:href里的静态文件路径
<link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
判断到是/static/开头,符合令牌条件,然后会到STATIC_URLS中的各个目录路径查找bootstrap-3.3.7-dist/css/bootstrap.min.css资源

#如果STATIC_URLS中第一个目录没有就到第二个目录查找,依次查找下去,都没有才会报错

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
#login
def login(request):
    # 返回一个登录界面
    return render(request,"login.html")

login.html,注意此时导入的路径直接/static/开头,不用加../回到上一级

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="/static/js/jQuery_3.5.1.js"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>

</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">登录界面</h1>
                <form action="" >
                    <p>
                        用户名: <input type="text" name="username" class="form-control">
                    </p>
                    <p>
                        密码: <input type="password" name="password" class="form-control">
                    </p>
                    <input type="submit" class="btn btn-success btn-block">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

浏览器访问:

方法二:在settings.py配置好静态后,再在login.html文件中使用模板语法,动态导入本地静态资源(建议使用)

settings.py

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

#静态文件配置
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static")
]

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <!--类似于导模块,这样html文件就能动态感知到本地静态资源的令牌,再写静态资源路径时也不用写令牌了-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">登录界面</h1>
                <form action="" >
                    <p>
                        用户名: <input type="text" name="username" class="form-control">
                    </p>
                    <p>
                        密码: <input type="password" name="password" class="form-control">
                    </p>
                    <input type="submit" class="btn btn-success btn-block">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

静态文件配置好之后,在浏览器也可以访问到static

回顾知识:

# form表单默认时get提交
http://127.0.0.1:8000/login/?username=alias&password=123

# form表单action参数
    1.不写 默认朝当前所在的url提交数据
    2.全写 指名道姓
    3.只写后缀 /login/

注意一个前期form的method的方式改为post时要注意的情况:

改为post之后浏览器访问会出现403:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <!--类似于导模块-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">登录界面</h1>
                <form action="" method="post">
                    <p>
                        用户名: <input type="text" name="username" class="form-control">
                    </p>
                    <p>
                        密码: <input type="password" name="password" class="form-control">
                    </p>
                    <input type="submit" class="btn btn-success btn-block">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

浏览器访问

解决方法1:配置文件中注释

# 在前期我们使用django提交post请求的时候 需要取配置文件中注释掉一行代码
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',
]

解决方法2:在form标签下面第一行添加 {% csrf_token %}

<form action="" method="post">
    {% csrf_token %}
    <p>
      用户名: <input type="text" name="username" class="form-control">
    </p>
    <p>
      密码: <input type="password" name="password" class="form-control">
    </p>
    <input type="submit" class="btn btn-success btn-block">
</form>

request对象方法初识

在views.py中的视图层方法里添加一个print(request),以Debug模式启动

request.method:返回请求方式,并且是全大写的字符串形式

示例:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
#login

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

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <!--类似于导模块-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">登录界面</h1>
                <form action="" method="post">
                    <p>
                        用户名: <input type="text" name="username" class="form-control">
                    </p>
                    <p>
                        密码: <input type="password" name="password" class="form-control">
                    </p>
                    <input type="submit" class="btn btn-success btn-block">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

request.POST:获取用户提交的post请求数据(不包含文件)

request.POST.get():获取列表的最后一个元素

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        print(request.POST)    # <QueryDict: {'username': ['alias'], 'password': ['123'], 'hobby': ['111', '222', '333']}>
        username = request.POST.get("username")
        print(username,type(username))   # alias <class 'str'>
        hobby = request.POST.get("hobby")
        print(hobby,type(hobby))     # 333 <class 'str'>

        return HttpResponse("收到了宝贝")
    return render(request, "login.html")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <!--类似于导模块-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">登录界面</h1>
                <form action="" method="post">
                    <p>
                        用户名: <input type="text" name="username" class="form-control">
                    </p>
                    <p>
                        密码: <input type="password" name="password" class="form-control">
                    </p>
                    <p>
                        <input type="checkbox" name="hobby" value="111">111
                        <input type="checkbox" name="hobby" value="222">222
                        <input type="checkbox" name="hobby" value="333">333
                    </p>
                    <input type="submit" class="btn btn-success btn-block">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

request.POST.getlist():获取整个列表

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        print(request.POST)    # <QueryDict: {'username': ['alias'], 'password': ['123'], 'hobby': ['111', '222', '333']}>
        # username = request.POST.get("username")
        # print(username,type(username))   # alias <class 'str'>
        # hobby = request.POST.get("hobby")    # get只会获取列表最后一个元素
        # print(hobby,type(hobby))     # 333 <class 'str'>
        username = request.POST.getlist("username")  # getlist会获取整个列表
        print(username, type(username))  # ['alias'] <class 'list'>
        hobby = request.POST.getlist("hobby")    # getlist会获取整个列表
        print(hobby, type(hobby))  # ['111', '222', '333'] <class 'list'>
        """
        总结:
        get只会获取列表最后一个元素
        """
        return HttpResponse("收到了宝贝")
    return render(request, "login.html")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <!--类似于导模块-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">登录界面</h1>
                <form action="" method="post">
                    <p>
                        用户名: <input type="text" name="username" class="form-control">
                    </p>
                    <p>
                        密码: <input type="password" name="password" class="form-control">
                    </p>
                    <p>
                        <input type="checkbox" name="hobby" value="111">111
                        <input type="checkbox" name="hobby" value="222">222
                        <input type="checkbox" name="hobby" value="333">333
                    </p>
                    <input type="submit" class="btn btn-success btn-block">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

request.GET:获取用户提交的get请求数据(不包含文件),用法和POST一样

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        return HttpResponse("收到了宝贝")
    # 获取url后面携带的参数
    # http://127.0.0.1:8000/login/?username=alias&password=123&hobby=111&hobby=222&hobby=333
    print(request.GET)   # <QueryDict: {'username': ['alias'], 'password': ['123'], 'hobby': ['111', '222', '333']}>
    print(request.GET.get("username"))    # get只获取列表最后一个元素,并且是字符串类型
    print(request.GET.getlist("hobby"))   # getlist 获取整个列表
    return render(request, "login.html")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <!--类似于导模块-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">登录界面</h1>
                <form action="" method="get">
                    <p>
                        用户名: <input type="text" name="username" class="form-control">
                    </p>
                    <p>
                        密码: <input type="password" name="password" class="form-control">
                    </p>
                    <p>
                        <input type="checkbox" name="hobby" value="111">111
                        <input type="checkbox" name="hobby" value="222">222
                        <input type="checkbox" name="hobby" value="333">333
                    </p>
                    <input type="submit" class="btn btn-success btn-block">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

总结

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请求则没有限制
"""

pycharm链接数据库(mysql)

pycharm中有类似Navicat一样的数据库客户端软件

软件位置

1、右上角

2、pycharm左下角

3、如果上面两个都没找到,在settings-Plugins里面搜database查看圈起来的插件是否安装了(默认都是安装的)

软件使用

1、点击一下

2、点击加号

3、点击mysql,一定要先安装对应的驱动

4、安装好对应驱动后,测试连接

测试连接,测试成功后点击apply==>点击ok

5、进入软件视图

6、在Navicat里先创建个表

7、在pycharm里面刷新,查看

8、按钮介绍

Django链接数据库(mysql)

Django默认使用的数据库是sqlite3

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

修改数据库为mysql

1、配置文件中配置

把原有的数据库配置注释掉

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

# 把原有的数据库配置注释掉
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }
# 连接MySQL数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day60',    # name对应数据库的名字
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8'
    }
}

2、代码声明

#django默认用的是mysqldb模块链接MySQL
    但是该模块的兼容性不好 需要手动改为用pymysql链接

# 你需要告诉django不要用默认的mysqldb,而是用pymysql
# 在项目名下的init或者任意的应用名下的init文件中书写以下代码都可以

这里我们在项目或者应用目录下的init.py文件中修改:

import pymysql
pymysql.install_as_MySQLdb()

ps:如果不进行第二步代码声明,会发现Django起不来了,报错如图:

Django之ORM简介

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

类                                 表

对象                               记录

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

需要操作应用下面的models.py文件
"""

1、先去应用下的models.py中书写一个类(模型类)==>表(模型表)

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
   verbose_name该参数是所有字段都有的 就是用来对字段的解释,加了是有好处的
    """ 
    # password int 
    password = models.IntegerField(verbose_name="密码")

2、数据库迁移命令(特别重要)

注意:在models.py里写完是没办法直接生效的,需要告诉ORM,要把上面models.py中的操作基于ORM映射到数据库里面去

两条命令:

#*************************# 2 数据库迁移命令*************************
python3 manage.py makemigrations 将操作记录记录到小本本上(就是应用中的migrations文件夹)

python3 manage.py migrate  将操作真正的同步到数据库中
# 只要你修改了models.py中跟数据库相关的代码 就必须重新执行上述的两条命令
#******************************************************************

点击pycharm的terminal终端,在终端里面输入这两条数据库迁移命令

# python3 manage.py makemigrations 将操作记录记录到小本本上(就是应用中的migrations文件夹)

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

执行完之后再查看数据库(记得刷新之后再查看)

表解释:

# app01_user表:就是我们通过ORM创建的表

#ps:
为什么会自动加个前缀app01呢?
因为一个Django项目可以有多个应用,那么多个应用之间可能会出现表名冲突的情况,加上前缀就可以完全避免,比较人性化

点开app01_user表看一看:

补充:

1、说明

# 由于一张表中必须要有一个主键字段 并且一般情况下都叫id字段
# 所以orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段
# 也就意味着 后续我们在创建模型表的时候如果主键字段名没有额外的叫法 那么主键字段可以省略不写

所以我们再models.py里面可以这么写:

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

2、数据库迁移命令,也可以在Tools-Run manage.py Task…里面写

不用写python3 manage.py,直接写命令(前期不建议使用)

如下:

# makemigrations   将操作记录记录到小本本上(应用下migrations文件夹中)

# migrate     将操作真正同步到数据库中

利用ORM实现数据的增删改查操作

字段的增删改查

先看一下环境:

user数据库:

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    password = models.IntegerField(verbose_name="密码")

增加字段

直接在models.py中的类的相应位置添加字段就可以,例如给user数据库添加一个age字段

表中已经有数据,添加字段第一种处理方法:执行# python3 manage.py makemigrations时出现选项后选1,立即给一个默认值

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    password = models.IntegerField(verbose_name="密码")
    age = models.IntegerField(verbose_name="年龄")

因为修改了跟数据库相关的代码,得执行一下数据库迁移命令:

# python manage.py makemigrations     # 注意:会有提示,这是因为user表中已经有数据

第一个选项:立刻给他设置一个默认值

第二个选项:离开之后手动给他添加一个默认值

# python3 manage.py migrate

表中已经有数据,添加字段第二种处理方法:在models.py的类中添加字段时,设置字段可以为空

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    password = models.IntegerField(verbose_name="密码")
    age = models.IntegerField(verbose_name="年龄")
    # null=True字段可以为空
    info = models.CharField(max_length=32,verbose_name="个人简介",null=True)

此时执行数据库迁移命令,就不会出现选项了。

表中已经有数据,添加字段第三种处理方法:在models.py的类中添加字段时,直接给默认值

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    password = models.IntegerField(verbose_name="密码")
    age = models.IntegerField(verbose_name="年龄")
    # null=True字段可以为空
    info = models.CharField(max_length=32,verbose_name="个人简介",null=True)
    # default直接给字段设置默认值
    hobby = models.CharField(max_length=32,verbose_name="兴趣爱好",default="study")

执行数据库迁移命令

修改字段

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

修改前的password字段类型

例如:我要把password的字段类型改成varchar类型

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")

    # password = models.IntegerField(verbose_name="密码")   #原先的
    password = models.CharField(max_length=32,verbose_name="密码")  #修改后的
    age = models.IntegerField(verbose_name="年龄")
    # null=True字段可以为空
    info = models.CharField(max_length=32,verbose_name="个人简介",null=True)
    # default直接给字段设置默认值
    hobby = models.CharField(max_length=32,verbose_name="兴趣爱好",default="study")

执行数据库迁移命令

# python3 manage.py makemigrations

# python3 manage.py migrate

修改后查看password类型

删除字段

把想删除的字段注释掉,然后再执行数据库迁移的两条命令即可(执行完毕之后字段对应的数据也都没有了)

比如说我想删除age,info以及hobby字段

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    # password = models.IntegerField(verbose_name="密码")   #原先的
    password = models.CharField(max_length=32,verbose_name="密码")  #修改后的
    # age = models.IntegerField(verbose_name="年龄")
    # # null=True字段可以为空
    # info = models.CharField(max_length=32,verbose_name="个人简介",null=True)
    # # default直接给字段设置默认值
    # hobby = models.CharField(max_length=32,verbose_name="兴趣爱好",default="study")

数据库迁移

# python3 manage.py makemigrations

# python3 manage.py migrate

查看

总结

"""
在操作models.py的时候一定要细心
    注释一些字段千万要小心,因为注释后执行迁移命令,字段对应的数据就都没了
    执行迁移命令之前最好先检查一下自己写的代码
"""

# 个人建议:当你离开你的计算机之后一定要锁屏

数据的增删改查:

看一下环境:

数据库:

查询数据:

查单条数据:models.User.objects.filter(条件)

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01 import models    # orm查询数据要依靠这个

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        #获取用户的用户名和密码 然后利用orm操作数据 校验数据是否正确
        username = request.POST.get("username")
        password = request.POST.get("password")

        # 去数据库中查询数据
        # select * from user where username='egon';   可以把filter联想成where记忆
        user_obj = models.User.objects.filter(username=username).first()     #拿到列表里的第一个元素
      # ps:filter()里面可以跟多个参数,用逗号隔开,参数之间是and关系
        # user_obj = models.User.objects.filter(username=username,password=password).first()   #select * from user where username='egon' and password = 'xxx';
        # ===============还可以使用索引取值====================
        # user_obj = models.User.objects.filter(username=username)
        # # print(user_obj)默认打印<QuerySet [<User: User object>]> 类似于列表套数据对象,[数据对象1,数据对象2],它也支持索引取值,切片操作,注意不支持负数
        # print(user_obj)     # 在models.py的对应添加__str__方法后,打印的是<QuerySet [<User: alias>]>
        # user_obj = res[0]   # 但是并不推荐使用索引取值,使用models.User.objects.filter(username=username).first()
        # print(user_obj.username)   # egon
        # print(user_obj.password)   # 123
        # =================================
        if user_obj:
            # 比对密码是否一致
            if password == user_obj.password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("密码错误")
        else:
            return HttpResponse("用户不存在")

    return render(request, "login.html")

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    # password = models.IntegerField(verbose_name="密码")   #原先的
    password = models.CharField(max_length=32,verbose_name="密码")  #修改后的
    # age = models.IntegerField(verbose_name="年龄")
    # # null=True字段可以为空
    # info = models.CharField(max_length=32,verbose_name="个人简介",null=True)
    # # default直接给字段设置默认值
    # hobby = models.CharField(max_length=32,verbose_name="兴趣爱好",default="study")

    def __str__(self):    #当对象被打印的时候,会触发这个方法
        return "%s" %self.username

查多条数据:select * from xxx

现有记录:

方式一:filter()括号内不加条件

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 登录功能
    url(r'^login/', views.login),
    # 注册功能
    url(r'^register/', views.register),
    # 展示功能
    url(r'^userlist/', views.userlist),
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01 import models  # orm查询数据要依靠这个

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        #获取用户的用户名和密码 然后利用orm操作数据 校验数据是否正确
        username = request.POST.get("username")
        password = request.POST.get("password")
        # 去数据库中查询数据
        # select * from user where username='egon';
        user_obj = models.User.objects.filter(username=username).first()     #拿到列表里的第一个元素
        # ===============还可以使用索引取值====================
        # user_obj = models.User.objects.filter(username=username)
        # # print(user_obj)默认打印<QuerySet [<User: User object>]> 类似于列表套数据对象,[数据对象1,数据对象2],它也支持索引取值,切片操作,注意不支持负数
        # print(user_obj)     # 在models.py的对应添加__str__方法后,打印的是<QuerySet [<User: alias>]>
        # user_obj = res[0]   # 但是并不推荐使用索引取值,使用models.User.objects.filter(username=username).first()
        # print(user_obj.username)   # egon
        # print(user_obj.password)   # 123
        # =================================
        if user_obj:
            # 比对密码是否一致
            if password == user_obj.password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("密码错误")
        else:
            return HttpResponse("用户不存在")

    return render(request, "login.html")

#注册
def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        user_obj = models.User.objects.filter(username=username).first()
        if user_obj:
            return HttpResponse("用户已经存在")
        # 直接获取用户数据存入数据库
        user_obj = models.User(username=username,password=password)
        user_obj.save()  #保存数据
    # 先给用户返回一个注册页面
    return render(request,"register.html")

# 展示功能
def userlist(request):
    # 查询出用户表里面所有的数据
    # 方式一:
    data = models.User.objects.filter()
    print(data)   # <QuerySet [<User: egon>, <User: tank>, <User: alias>, <User: wangpeng>, <User: jc>]>
    # 因为在models.py中加了__str__方法,否则默认显示为<QuerySet [<User: User object>, <User: User object>, <User: User object>, <User: User object>, <User: User object>]>

    return HttpResponse("userlist")

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    password = models.CharField(max_length=32,verbose_name="密码")  #修改后的

    def __str__(self):    #当对象被打印的时候,会触发这个方法
        return "%s" %self.username

方法二:models.User.objects.all() 推荐方式

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 登录功能
    url(r'^login/', views.login),
    # 注册功能
    url(r'^register/', views.register),
    # 展示功能
    url(r'^userlist/', views.userlist),
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01 import models  # orm查询数据要依靠这个

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        #获取用户的用户名和密码 然后利用orm操作数据 校验数据是否正确
        username = request.POST.get("username")
        password = request.POST.get("password")
        # 去数据库中查询数据
        # select * from user where username='egon';
        user_obj = models.User.objects.filter(username=username).first()     #拿到列表里的第一个元素
        # ===============还可以使用索引取值====================
        # user_obj = models.User.objects.filter(username=username)
        # # print(user_obj)默认打印<QuerySet [<User: User object>]> 类似于列表套数据对象,[数据对象1,数据对象2],它也支持索引取值,切片操作,注意不支持负数
        # print(user_obj)     # 在models.py的对应添加__str__方法后,打印的是<QuerySet [<User: alias>]>
        # user_obj = res[0]   # 但是并不推荐使用索引取值,使用models.User.objects.filter(username=username).first()
        # print(user_obj.username)   # egon
        # print(user_obj.password)   # 123
        # =================================
        if user_obj:
            # 比对密码是否一致
            if password == user_obj.password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("密码错误")
        else:
            return HttpResponse("用户不存在")

    return render(request, "login.html")

#注册
def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        user_obj = models.User.objects.filter(username=username).first()
        if user_obj:
            return HttpResponse("用户已经存在")
        # 直接获取用户数据存入数据库
        user_obj = models.User(username=username,password=password)
        user_obj.save()  #保存数据
    # 先给用户返回一个注册页面
    return render(request,"register.html")

# 展示功能
def userlist(request):
    # 查询出用户表里面所有的数据
    # 方式二:
    data = models.User.objects.all()
    print(data)   # <QuerySet [<User: egon>, <User: tank>, <User: alias>, <User: wangpeng>, <User: jc>]>
    # 因为在models.py中加了__str__方法,否则默认显示为<QuerySet [<User: User object>, <User: User object>, <User: User object>, <User: User object>, <User: User object>]>

    return HttpResponse("userlist")

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    password = models.CharField(max_length=32,verbose_name="密码")  #修改后的

    def __str__(self):    #当对象被打印的时候,会触发这个方法
        return "%s" %self.username

数据的增加:

增的方法一:models.User.objects.create()

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^register/', views.register),
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01 import models  # orm查询数据要依靠这个

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        #获取用户的用户名和密码 然后利用orm操作数据 校验数据是否正确
        username = request.POST.get("username")
        password = request.POST.get("password")
        from app01 import models  # orm查询数据要依靠这个
        # 去数据库中查询数据
        # select * from user where username='egon';
        user_obj = models.User.objects.filter(username=username).first()     #拿到列表里的第一个元素
        # ===============还可以使用索引取值====================
        # user_obj = models.User.objects.filter(username=username)
        # # print(user_obj)默认打印<QuerySet [<User: User object>]> 类似于列表套数据对象,[数据对象1,数据对象2],它也支持索引取值,切片操作,注意不支持负数
        # print(user_obj)     # 在models.py的对应添加__str__方法后,打印的是<QuerySet [<User: alias>]>
        # user_obj = res[0]   # 但是并不推荐使用索引取值,使用models.User.objects.filter(username=username).first()
        # print(user_obj.username)   # egon
        # print(user_obj.password)   # 123
        # =================================
        if user_obj:
            # 比对密码是否一致
            if password == user_obj.password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("密码错误")
        else:
            return HttpResponse("用户不存在")

    return render(request, "login.html")

#注册
def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")

        user_obj = models.User.objects.filter(username=username).first()
        if user_obj:
            return HttpResponse("用户已经存在")
        # 直接获取用户数据存入数据库
        res = models.User.objects.create(username=username,password=password)
        # res返回值就是当前被创建的对象本身
        print(res)  # alias,这是个对象,打印这个是因为之前在models.py对应的类里添加l__str__方法
    # 先给用户返回一个注册页面
    return render(request,"register.html")

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    # password = models.IntegerField(verbose_name="密码")   #原先的
    password = models.CharField(max_length=32,verbose_name="密码")  #修改后的
    # age = models.IntegerField(verbose_name="年龄")
    # # null=True字段可以为空
    # info = models.CharField(max_length=32,verbose_name="个人简介",null=True)
    # # default直接给字段设置默认值
    # hobby = models.CharField(max_length=32,verbose_name="兴趣爱好",default="study")

    def __str__(self):    #当对象被打印的时候,会触发这个方法
        return "%s" %self.username

增的方式二:实例化类

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01 import models  # orm查询数据要依靠这个

# Create your views here.
#login
def login(request):
    """
    get请求和post请求应该有不同的处理机制,可以使用request的对象方法
    :param request:请求相关的数据对象,里面有很多简易的方法
    :return:
    """
    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        #获取用户的用户名和密码 然后利用orm操作数据 校验数据是否正确
        username = request.POST.get("username")
        password = request.POST.get("password")
        from app01 import models  # orm查询数据要依靠这个
        # 去数据库中查询数据
        # select * from user where username='egon';
        user_obj = models.User.objects.filter(username=username).first()     #拿到列表里的第一个元素(推荐使用这种方法)
        # ===============还可以使用索引取值====================
        # user_obj = models.User.objects.filter(username=username)
        # # print(user_obj)默认打印<QuerySet [<User: User object>]> 类似于列表套数据对象,[数据对象1,数据对象2],它也支持索引取值,切片操作,注意不支持负数
        # print(user_obj)     # 在models.py的对应添加__str__方法后,打印的是<QuerySet [<User: alias>]>
        # user_obj = res[0]   # 但是并不推荐使用索引取值,使用models.User.objects.filter(username=username).first()
        # print(user_obj.username)   # egon
        # print(user_obj.password)   # 123
        # =================================
        if user_obj:
            # 比对密码是否一致
            if password == user_obj.password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("密码错误")
        else:
            return HttpResponse("用户不存在")

    return render(request, "login.html")

#注册
def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        user_obj = models.User.objects.filter(username=username).first()
        if user_obj:
            return HttpResponse("用户已经存在")
        # 实例化类
        user_obj = models.User(username=username,password=password)
        user_obj.save()  #保存数据
    # 先给用户返回一个注册页面
    return render(request,"register.html")

models.py

from django.db import models

# Create your models here.
# 类 -- 表
class User(models.Model):    # 一定要继承父类models.Model
    # id int primary auto_increment
    id = models.AutoField(primary_key=True,verbose_name="主键")  # 此句等同于设置id字段为主键并且自增的sql语句;
    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    """
    CharField必须要指定max_length参数,不写直接报错
    """
    # password int
    # password = models.IntegerField(verbose_name="密码")   #原先的
    password = models.CharField(max_length=32,verbose_name="密码")  #修改后的
    # age = models.IntegerField(verbose_name="年龄")
    # # null=True字段可以为空
    # info = models.CharField(max_length=32,verbose_name="个人简介",null=True)
    # # default直接给字段设置默认值
    # hobby = models.CharField(max_length=32,verbose_name="兴趣爱好",default="study")

    def __str__(self):    #当对象被打印的时候,会触发这个方法
        return "%s" %self.username

数据的修改

# 后端查询出用户想要编辑的数据对象 展示到前端页面供用户查看和编辑
  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
        # models.User.objects.filter(id=edit_id).update(username=username,password=password)
        """
            将filter查询出来的列表中所有的对象全部更新            批量更新操作,取决于filter(条件)查找到的对象个数
            只修改被修改的字段
        """

        # 修改数据方式2,通过对象赋值,再save(),这是单个更新
        edit_obj.username = username
        edit_obj.password= password
        edit_obj.save()
        """
            方法2当字段特别多的时候效率会非常的低
            从头到尾将数据的所有字段全部更新一边 无论该字段是否被修改
        """

        # 跳转到数据的展示页面
        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()
    """
        批量删除
    """

    """       
    方法二:通过对象删除,单个删除       
    user_obj = models.User.objects.filter(id=delete_id).first()       
    user_obj.delete()    
    """
    # 跳转到展示页面

    return redirect('/userlist/')

示例:

功能描述:将用户信息在前端展示给用户,供用户编辑或删除,

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 登录功能
    url(r'^login/', views.login),
    # 注册功能
    url(r'^register/', views.register),
    # 展示功能
    url(r'^userlist/', views.userlist),
    # 编辑用户
    url(r'^edit_user/', views.edit_user),
    # 删除用户
    url(r'^delete_user/', views.delete_user),
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01 import models  # orm查询数据要依靠这个

# Create your views here.
#login
def login(request):

    # print(request.method)    # request.method:返回请求方式,并且是全大写的字符串形式
    if request.method == "POST":
        #获取用户的用户名和密码 然后利用orm操作数据 校验数据是否正确
        username = request.POST.get("username")
        password = request.POST.get("password")
        # 去数据库中查询数据
        # select * from user where username='egon';
        user_obj = models.User.objects.filter(username=username).first()     #拿到列表里的第一个元素

        if user_obj:
            # 比对密码是否一致
            if password == user_obj.password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("密码错误")
        else:
            return HttpResponse("用户不存在")

    return render(request, "login.html")

#注册
def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        user_obj = models.User.objects.filter(username=username).first()
        if user_obj:
            return HttpResponse("用户已经存在")
        # 直接获取用户数据存入数据库
        user_obj = models.User(username=username,password=password)
        user_obj.save()  #保存数据
    # 先给用户返回一个注册页面
    return render(request,"register.html")

# 展示功能
def userlist(request):
    # 查询出用户表里面所有的数据
    user_queryset = models.User.objects.all()
    # print(user_queryset)   # <QuerySet [<User: egon>, <User: tank>, <User: alias>, <User: wangpeng>, <User: jc>]>
    # 因为在models.py中加了__str__方法,否则默认显示为<QuerySet [<User: User object>, <User: User object>, <User: User object>, <User: User object>, <User: User object>]>

    return render(request,'userlist.html',{"user_queryset":user_queryset})

# 编辑用户
def edit_user(request):
    # 接收前端发过来的user_id
    edit_id = request.GET.get("user_id")

    # 获取提交过来的用户名和密码
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        # 去数据库中修改对应的数据内容
        models.User.objects.filter(id=edit_id).update(username=username,password=password)
        """
        将filter查询出来的列表中所有的对象全部更新    批量更新操作
        """
        return redirect("/userlist/")

    # 查询出想要编辑的用户信息,展示到前端供用户编辑
    edit_obj = models.User.objects.filter(id=edit_id).first()
    #将数据对象展示到页面上
    return render(request,"edit_user.html",{"edit_obj":edit_obj})

# 删除用户
def delete_user(request):
    # 接收前端发过来的user_id
    delete_id = request.GET.get("user_id")

    #直接去数据库中找到对应的数据删除
    models.User.objects.filter(id=delete_id).delete()
    """
    批量删除
    """
    return redirect("/userlist/")

userlist.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <!--类似于导模块-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">数据展示</h1>
                <table class="table table-striped table-hover">
                    <thead>
                        <tr>
                            <th>id</th>
                            <th>username</th>
                            <th>password</th>
                            <th>action</th>
                        </tr>
                    </thead>
                    {% for user_obj in user_queryset %}
                        <tr>
                            <td>{{ user_obj.id }}</td>
                            <td>{{ user_obj.username }}</td>
                            <td>{{ user_obj.password }}</td>
                            <td>
                                <!--用户点了编辑之后,通过?后面跟k,v的方法将编辑的用户id发送给后端;/edit_user/?user_id={{ user_obj.id }}-->
                                <a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>
                                <a href="/delete_user/?user_id={{ user_obj.id }}" class="btn btn-danger btn-xs">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                </table>
            </div>
        </div>
    </div>
</body>
</html>

edit_user.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>数据编辑</title>

    <!--类似于导模块-->
    {% load static %}
    <!-- Bootstrap3 核心 CSS 文件,本地导入 -->
    <link href="{% static "bootstrap-3.3.7-dist/css/bootstrap.min.css" %}" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="{% static "js/jQuery_3.5.1.js" %}"></script>
    <!-- Bootstrap3 核心 JavaScript 文件 -->
    <script src="{% static "bootstrap-3.3.7-dist/js/bootstrap.min.js" %}"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">数据编辑</h1>
                <form action="" method="post">
                    <p>
                        用户名: <input type="text" name="username" class="form-control" value="{{ edit_obj.username }}">
                    </p>
                    <p>
                        密码: <input type="text" name="password" class="form-control" value="{{ edit_obj.password }}">
                    </p>
                    <input type="submit" class="btn btn-info btn-block" value="编辑">
                </form>
            </div>
        </div>
    </div>
</body>
</html>

界面效果

补充

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

ORM中创建表关系

"""
表与表之间的关系
    一对多

    多对多

    一对一

    没有关系

判断表关系的方法:换位思考
"""

我们以图书表,出版社表,作者表,以及作者详情表为例:

# 图书表  
# 出版社表
# 作者表
# 作者详情表

"""
图书和出版社是一对多的关系,外键字段建在多的一方,图书是多的一方
图书和作者是多对多的关系,要建一个中间表book2author记录图书和作者的关系
作者表和作者详情表是一对一
"""

Django连接数据库

settings.py,注释原有数据库配置

# 连接mysql数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day61',    # name对应数据库的名字
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8'
    }
}

在项目或应用下的init.py中添加

import pymysql
pymysql.install_as_MySQLdb()

创建模型类:

ps:django1.11.11中orm创建的外键字段默认就是级联更新、级联删除的

models.py

from django.db import models

# Create your models here.
# 创建表关系 先将基表创建出来,然后再添加外键字段

# 图书表
class Book(models.Model):
    title = models.CharField(max_length=32,verbose_name="图书名")
    price = models.DecimalField(max_digits=8,decimal_places=2,verbose_name="价格")
    # max_digits=8,decimal_places=2:小数总共八位,小数点后面占两位
    """
    图书和出版社是一对多关系,并且图书是多的一方,所以外键字段放在图书表里
    """
    publish = models.ForeignKey(to="Publish")          #一对多表关系  #publish是和Publish表关联的外键字段,默认是和Publish表的主键id字段关联,也可以使用to_field="id"指定

    """
    图书和作者是多对多关系,在ORM中不用手动创建中间表了,ORM会自动帮我们创建中间表,ORM中外键字段建在任意一方均可,但是推荐建在查询频率较高的一方    ps:    如果字段对应的是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,verbose_name="出版社名称")
    addr = models.CharField(max_length=32,verbose_name="出版社地址")

# 作者
class Author(models.Model):
    name = models.CharField(max_length=32,verbose_name="姓名")
    age = models.IntegerField(verbose_name="年龄")
    """
    作者和作者详情是一对一关系,外键字段建在任意一方都可以,推荐建在查询频率较高的一方,这里外键建在作者表中
    """
    author_detail = models.OneToOneField(to="AuthorDetail")     #一对一表关系    # OneToOneField也会自动给字段加_id后缀

#作者详情表
class AuthorDetail(models.Model):
    phone = models.BigIntegerField(verbose_name="手机号")
    addr = models.CharField(max_length=32,verbose_name="作者地址")

执行数据库迁移命令

# python3 manage.py makemigrations
# python3 manage.py migrate

查看数据库中的表

解释:

圈红圈的忽略:django自动创建的

app01_author:作者表

app01_authordetail:作者详情表

app01_book:图书表

图书表模型类代码

# 图书表
class Book(models.Model):
    title = models.CharField(max_length=32,verbose_name="图书名")
    price = models.DecimalField(max_digits=8,decimal_places=2,verbose_name="价格")
    # max_digits=8,decimal_places=2:小数总共八位,小数点后面占两位
    """
    图书和出版社是一对多关系,并且图书是多的一方,所以外键字段放在图书表里
    """
    publish = models.ForeignKey(to="Publish")          #一对多表关系  #publish是和Publish表关联的外键字段,默认是和Publish表的主键id字段关联,也可以使用to_field="id"指定

    """
    图书和作者是多对多关系,在ORM中不用手动创建中间表了,ORM会自动帮我们创建中间表,ORM中外键字段建在任意一方均可,但是推荐建在查询频率较高的一方
    """
    authors = models.ManyToManyField(to="Author")      # 多对多表关系
    """
    authors 是一个虚拟字段,主要用来告诉ORM 图书表和作者表是多对多的关系
    让ORM自动帮你创建第三方中间表
    """

我们发现代码中加上id主键应该有五个字段(id、title、price、publish、authors)

但是在数据库表中只有(id、title、price、publish_id)

现在来解释:

为什么代码里写的外键名是publish,但是在数据库中是publish_id?

#ForeignKey   一对多外键
# OneToOneField  一对一外键
# 会自动在字段后面加_id后缀

为什么只有四个字段?

因为代码中authors是虚拟字段,主要用来告诉ORM 图书表和作者表是多对多的关系,让ORM自动帮你创建第三方中间表(就是多出来的表app01_book_authors)

app01_book_authors:这是django自动帮我们创建的图示表与作者表之间的中间表

app01_publish:出版社表

orm表与表关系创建总结

# orm中如何定义三种关系
    publish = models.ForeignKey(to='Publish')  # 一对多,默认就是与出版社表的主键字段做外键关联,也可以使用to_field="id"指定

    authors = models.ManyToManyField(to='Author')   # 多对多表关系

    author_detail = models.OneToOneField(to='AuthorDetail')   # 一对一表关系

# ps:        
    ForeignKey
    OneToOneField
    会自动在字段后面加_id后缀

补充:

# 在django1.X版本中外键默认都是级联更新删除的
# 多对多的表关系可以有好几种创建方式 这里暂且先介绍一种
"""
  一对多
      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查询方便)

  判断表关系的方式:换位思考
  """
文档更新时间: 2022-02-28 17:34   作者:李延召