零基础入手Django(六):模型基础1
滴水石穿,绳锯木断~学习贵在持之以恒!

今天是2019年1月19日,小叮当继续为大家分享Django干货。主要内容有:Django的ORM简介、数据库连接配置、模型的创建与映射、数据的增删改查。

一、Django的ORM简介
1.ORM
ORM的全称是Object Relational Mapping翻译过来就是对象关系映射的意思。
2.ORM的优势
不用直接编写SQL代码,只需像操作对象一样从数据库操作数据。

3.django模型映射关系
django中模型类、类属性和数据库的对应关系如下:

(1)模型类必须都写在app下的models.py文件中。
(2)模型如果需要映射到数据库,所在的app必须被安装.
(3)一个数据表对应一个模型类,表中的字段,对应模型中的类属性.
二、数据库连接配置
准备工作
(1)在项目的主目录下找到settings.py文件中的“DATABASES"

其中” ENGINE“表示存储引擎,默认连接的是”sqlite3"数据库。“sqlite3"是Django中自带的一个小巧数据库。
我们以常使用mysql数据库为例说明:
(2)将默认的”DATABASES"注释掉

(3)在xshell中使用命令进入mysql
mysql -u root -p
用户名密码如下

如上使用root用户后,输入密码qwe123即可进入mysql

(4)建立新的数据库管理用户
创建一个管理员用户xdd(小叮当)账号,密码为xdd:
CREATE USER 'xdd'@'%'IDENTIFIED BY 'xdd';
给这个"xdd"用户授予所有远程访问,这个用户主要用于管理整个数据库,备份,还原等操作。
GRANT ALL ON *.* TO 'xdd'@'%';
使授权立即生效:
FLUSH PRIVILEGES;
操作如下

(5)查看当前数据库,并新建数据库用于django项目
使用命令查看数据库
show databases;
查看结果

新建数据库,名为“mydb”
create database mydb;
结果如下:

2.配置数据库连接
(1)在主目录的settings.py中写入如下连接代码:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'mydb', #数据库名称
'USER': 'xdd', # 链接数据库的用户名
'PASSWORD': 'xdd', # 链接数据库的密码
'HOST': '192.168.255.130', # mysql服务器的域名和ip地址
'PORT': '3306', # mysql的一个端口号,默认是3306
}
}
如下图所示

3.pymysql数据库连接器配置
使用“exit"退出mysql

”在我们的django虚拟环境中安装pymysql
(1)进入项目虚拟环境查看是否装有pymysql
查看当前虚拟环境
workon
进入项目虚拟环境
workon djtest2.1
查看当前安装包
pip list
结果如下

(2)如果没有pymysql使用命令安装pymysql
安装pymysql
pip install pymysql
如下

(3)配置pymysql(因为django默认的配置不是pymysql)
在主目录的“_init_py”中写入如下代码
import pymysql
pymysql.install_as_MySQLdb()
如下

这时pymysql下可能会有“红波浪线”提示

我们点击pycharm中的file----settings----project interpreter 查看,只要确认我们配置的远程解释器中已安装pymysql即可。

三、模型的创建与映射
1.新建测试app
(1)在pycharm的“tool"中找到”Run manage.py Task...“

(2)使用命令新建app名为model_test
命令为:
startapp model_test
结果如下

(3)在项目文件夹”hello_django“处右键,使用deployment进行download下载。

执行完毕后即可发现我们新建的"model_test"
(4)在主目录“settings.py"中注册app
在INSTALLED_APPS列表中添加”model_test“

2.创建类
我们在mode_test下找到models.py创建user类(数据表)
from django.db import models
# Create your models here.
#类---数据表
#类属性---字段
#1.定义模型类(数据表)
class User(models.Model):
#配置id字段,设置为自增长,并设为主键(也可省略,使用系统默认设置的id)
id = models.AutoField(primary_key=True)
#配置name字段,设置为字符类型,最大长度为50
name = models.CharField(max_length=50)
#配置age字段,设置为整数类型
age = models.IntegerField(max_length=50)
3.生成映射文件
(1)方法一:在linux系统对应项目目录中执行命令
python manage.py makemigrations model_test
(2)方法二:在pycharm中执行

值得注意,如果makemigrations命令后面不加app的名字,系统默认为所有app生成映射文件。
我们执行”deployment"中的“download"进行代码同步后,查看model_test下的migrations文件夹即可看到我们生成的”0001_intial.py“映射文件。

4.将映射文件数据提交到数据库
(1)方法一:在linux系统对应项目目录中执行命令
python manage.py migrate model_test
(2)方法二:在pycharm中执行

同样,migrate命令后不跟app的名字时,系统默认为全部app做数据库的映射。
5.在服务器端登录数据库进行查看
使用我们创建的xdd用户进行登录mysql
mysql -u xdd -p
输入密码xdd后,使用我们连接到django项目的mydb数据库
use mydb;
查看表格
show tables;
结果如下

可以看到系统为我们创建的表“model_test_user"
值得注意的是,其命名规则为:app名字+下划线+类名的小写
在本例中,我们的app名字为model_test 我们创建的类名为User
所以系统为我们创建了名字为”model_test_user"的表。
四、数据的增删改查
前言
使用Djiango对数据库进行增删改查时,我们需要了解一下数据库相关的接口(QuerySet API)
①从数据库中查询出来的结果一般是一个集合,这个集合叫做 QuerySet.
②QuerySet是可迭代对象.
③.QuerySet支持切片, 不支持负索引.
④可以用list强行将QuerySet变成列表.
1.环境配置
(1)在model_test下的views.py中导入我们定义好的user类并定义好增删改查的视图函数框架(用pass代替函数体)

代码如下:
from django.shortcuts import render
# Create your views here.
from .models import User
from django.http import HttpResponse
#增加数据
def add_user(request):
pass
#删除数据
def delete_user(request):
pass
#更改数据
def update_user(request):
pass
#查询数据
def search_user(request):
pass
(2)在model_test下新建urls.py,在主目录中的urls.py中为model_test分配路由。
在model_test下新建urls.py

在主目录中为model_test分配路由

代码如下
path('model/',include('model_test.urls')),
(3)在mode_test下的urls.py中配置分路由
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'IT小叮当'
__time__ = '2019-01-22 20:00'
from django.contrib import admin
from django.urls import path,re_path,include
from . import views
urlpatterns = [
path('add/',views.add_user),
path('delete/',views.delete_user),
path('update/',views.update_user),
path('search/',views.search_user),
]
3.编写添加数据视图函数
方法一:实例化类进行传参
(1)在视图函数中重新定义add_user
def add_user(request):
#方法一
xdd = User(name='xdd',age=18)
xdd.save()
return HttpResponse('小叮当插入数据成功!')
(2)在浏览器中访问

(3)xshell连接服务端查看mysql

方法二:先实例化类后传参
(1)在视图函数中重新定义add_user
def add_user(request):
#方法二
xdd=User()
xdd.name = '小叮当'
xdd.age = 18
xdd.save()
return HttpResponse('小叮当使用方法二插入数据成功!')
(2)在浏览器中访问

(3)xshell连接服务端查看mysql

方法三:使用objects.create传参
(1)在视图函数中重新定义add_user
def add_user(request):
#方法三
User.objects.create(name='老叮当',age=19)
return HttpResponse('小叮当使用方法三插入数据成功!')
(2)在浏览器中访问

(3)xshell连接服务端查看mysql

值得注意,当我们再次刷新添加数据页面后,查看mysql,发现数据已然重复~

刷新后,查看mysql

那么,怎样才能在刷新页面的同时,不会造成数据库的重复添加呢?下面,我们来看方法四~
方法四:使用objects.get_or_create()传参
(1)在视图函数中重新定义add_user
def add_user(request):
#方法四
User.objects.get_or_create(name='小小叮当',age=17)
return HttpResponse('小叮当使用方法四插入数据成功!')
(2)在浏览器中访问

(3)xshell连接服务端查看mysql

再次刷新网页

查看mysql

可以看到,使用方法四get_or_create()传参新增的数据不会出现重复。
4.查询数据
由于更改和删除操作都是建立在查询的基础上,所以我们先来了解在django中如何查询数据。
查询所有 objects.all()
(1)在视图函数中重新定义search_user
def search_user(request):
#查询所有数据
all_info = User.objects.all()
return HttpResponse(all_info)
(2)在浏览器中访问

这时,我们发现浏览器中出现了5个用户对象,但好像什么都看不出来!这就需要我们在User类中,重新定义输出方法了。
(3)在models.py里的User类中,重新定义输出方法__str__
class User(models.Model):
#配置id字段,设置为自增长,并设为主键(也可省略,使用系统默认设置的id)
id = models.AutoField(primary_key=True)
#配置name字段,设置为字符类型,最大长度为50
name = models.CharField(max_length=50)
#配置age字段,设置为整数类型
age = models.IntegerField(max_length=50)
#定义输出
def __str__(self):
return 'User'%(self.id,self.name,self.age)
(4)在浏览器中查看

这次变成了5个连续的User,也不是我们想要看到的结果啊!这是因为__str__()方法(注意str前后是两个下横线)对print有效。
我们在视图函数中,加入print语句在后台查看,
#查询数据
def search_user(request):
#查询所有数据
all_info = User.objects.all()
print(all_info)
return HttpResponse(all_info)
在后台查看如下

可以看到,此时已经可以输出我们想要查询的结果了。
条件查询 objects.filter()
(1)定义视图函数
def search_user(request):
#查询所有数据
# all_info = User.objects.all()
# print(all_info)
# 查询满足条件
meet_info = User.objects.filter(name='小叮当')
print(meet_info)
return HttpResponse(meet_info)
(2)浏览器中查看

(3)后台查看

定义视图函数,对比输出
#查询数据def search_user(request): #查询所有数据 all_info = User.objects.all()
# print(all_info) # 查询满足条件 meet_info = User.objects.filter(name='小叮当') #QuerSet print('我是查询到的所有QuerSset',all_info)
print('我是一条数据',meet_info[0]) #一个模型类的实例对象----数据表的一条数据 return HttpResponse(meet_info)
在浏览器端刷新后,再次在后台查看

条件查询 objects.get()
定义视图函数
#查询数据
def search_user(request):
meet_info = User.objects.get(id=3)
print('我通过get方法得到',meet_info)
return HttpResponse(meet_info)
浏览器中刷新后,在后台查看

值得注意,使用objects.get()方法进行查询时,查询的条件需要确保“唯一性”,例如id等字段。
5.更新数据
更新数据的思路就是:先查找到数据,再进行更新操作
方法一:get()方法找到数据,再属性赋值修改后保存
(1)定义视图函数
#更改数据
def update_user(request):
meet_info = User.objects.get(id=3)
meet_info.name='不老叮当'
meet_info.save()
return HttpResponse('我将老叮当改为了,不老叮当!')
(2)浏览器中查看

(3)在xshell中查看数据库

可以看到,id为3的老叮当,已经被成功修改为不老叮当~
方法二:使用filter()查询数据,用其自带的update()方法进行数据更新
(1)定义视图函数
#更改数据
def update_user(request):
User.objects.filter(name='不老叮当').update(name='神仙小叮当')
return HttpResponse('我将不老叮当改成了神仙小叮当!')
(2)浏览器中查看

(3)xshell查看服务端数据库

可以看到,“不老叮当”已经被成功改为“神仙小叮当”了。
添加新的字段
当我们想要为数据表添加新的字段时,在models.py中的模型类中添加即可。需要注意的是,添加字段会改变表的结构,因此需要重新生成映射文件,将映射文件提交到数据库。
(1)在模型类中添加新字段
class User(models.Model):
#配置id字段,设置为自增长,并设为主键(也可省略,使用系统默认设置的id)
id = models.AutoField(primary_key=True)
#配置name字段,设置为字符类型,最大长度为50
name = models.CharField(max_length=50)
#配置age字段,设置为整数类型
age = models.IntegerField(max_length=50)
#添加新字段,一定要设置最大长度和默认值
city = models.CharField(max_length=50,default='洛阳')
#定义输出
def __str__(self):
return 'User'%(self.id,self.name,self.age)
(2)生成映射文件
在tools中找到“Run manage.py Task"

执行命令makemigrations model_test


可以看到,city字段已被添加到user模型类中。
(3)将映射文件提交到数据库
执行命令migrate model_test


可以看到,city字段已经添加完成。
(4)在xshell中查看数据库

可以看到city字段已经添加成功。
将某个字段的值全部修改为特定值
例如,我们将city中的”洛阳“全部修改为”北京“
(1)定义视图函数
def update_user(request):
User.objects.all().update(city='北京')
return HttpResponse('我将所有的city属性全改为了北京!')
(2)在浏览器中查看

(3)通过xshell查看服务器端的数据库

可以看到,所有city字段已更改为了”北京“。
6.删除数据
方法一:通过objects.get().delete()来删除数据
(1)定义视图函数
#删除数据
def delete_user(request):
User.objects.get(id=4).delete()
return HttpResponse('我删除了id=4的数据!')
(2)浏览器中查看

(3)通过xshell在服务端查看数据库

方法二:通过objects.filter().delete()来删除数据
(1)定义视图函数
#删除数据
def delete_user(request):
# User.objects.get(id=4).delete()
User.objects.filter(name='小小叮当').delete()
return HttpResponse('我删除name为小小叮当的数据!')
(2)浏览器中查看

(3)xshell中查看服务端数据库

可以看到名为“小小叮当”的数据已被我们成功删除~