- 以登录功能为例:
- 准备
- 静态文件配置
- 方法一:在项目配置文件settings.py配置静态文件
- 方法二:在settings.py配置好静态后,再在login.html文件中使用模板语法,动态导入本地静态资源(建议使用)
- 回顾知识:
- 注意一个前期form的method的方式改为post时要注意的情况:
- 解决方法1:配置文件中注释
- 解决方法2:在form标签下面第一行添加 {% csrf_token %}
- request对象方法初识
- request.method:返回请求方式,并且是全大写的字符串形式
- request.POST:获取用户提交的post请求数据(不包含文件)
- request.POST.get():获取列表的最后一个元素
- request.POST.getlist():获取整个列表
- request.GET:获取用户提交的get请求数据(不包含文件),用法和POST一样
- 总结
- pycharm链接数据库(mysql)
- pycharm中有类似Navicat一样的数据库客户端软件
- 软件位置
- 软件使用
- Django链接数据库(mysql)
- 修改数据库为mysql
- Django之ORM简介
- 1、先去应用下的models.py中书写一个类(模型类)==>表(模型表)
- 2、数据库迁移命令(特别重要)
- 两条命令:
- 点击pycharm的terminal终端,在终端里面输入这两条数据库迁移命令
- 补充:
- 利用ORM实现数据的增删改查操作
- 字段的增删改查
- 增加字段
- 表中已经有数据,添加字段第一种处理方法:执行# python3 manage.py makemigrations时出现选项后选1,立即给一个默认值
- 表中已经有数据,添加字段第二种处理方法:在models.py的类中添加字段时,设置字段可以为空
- 表中已经有数据,添加字段第三种处理方法:在models.py的类中添加字段时,直接给默认值
- 修改字段
- 删除字段
- 总结
- 数据的增删改查:
- 查询数据:
- 查单条数据:models.User.objects.filter(条件)
- 查多条数据:select * from xxx
- 数据的增加:
- 增的方法一:models.User.objects.create()
- 增的方式二:实例化类
- 数据的修改
- 数据的删除
- 补充
- ORM中创建表关系
- Django连接数据库
- 创建模型类:
- 查看数据库中的表
- orm表与表关系创建总结
以登录功能为例:
如果我们用在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查询方便)
判断表关系的方式:换位思考
"""