Django数据库相关
一、pycharm链接数据库
pycharm有类似Navicat的图形化管理数据库功能,默认有安装没有则安装插件database tools and SQL,要么右上角要么左下角有个database按钮,点开后一定要安装提示的download missing驱动文件,点击下载即可,其余使用跟Navicat差不多。
图形化方式连接数据库:
二、Django连接数据库
1.1、配置文件中开启配置
在settings - DATABASES那里默认的ENGINE是SQLite换成MySQL,name是要连接的数据库名,其它都是很熟悉的味道了。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'study',
'USER': 'root',
'PASSWORD': 'sanxi666',
'HOST': '127.0.0.1',
'PORT': '3306',
'CHARSET': 'utf8'
}
}
1.2、代码声明
django默认用的是mysqldb模块连接数据库,这模块兼容性不好,需要改为pymysql;因此需要在项目名下的init或者任意的APP名下的init文件中,书写以下代码:
import pymysql
pymysql.install_as_MySQLdb()
三、Django ORM
ORM,对象关系映射,号称能让一个不会SQL语句的小白也能通过Python面向对象的代码简单快捷地操作数据库;缺点?当然是因为封装程度过高,有时候SQL语句的执行效率偏低,可能需要自己写SQL语句。
3.1、创建表
因为是通过Python的面向对象代码,因此我们需要在APP下面的models.py自定义类
class User(models.Model):,一定要继承这个
等价于id int primary_key auto_increment
id = models.AutoField(primary_key=True, verbose_name='主键')
# username varchar(32),charfield必须要指定max_length,否则报错
# verbose是所有字段都有的,就是用来对字段的解释
username = models.CharField(max_length=32,verbose_name='用户名')
password = models.IntegerField()
# 由于一张表中必须要有一个主键,一般都叫id,当没定义时ORM会自动创建一个名为id的主键字段
3.2、数据库迁移命令(重点)
只要修改了models中跟数据库相关的代码,就必须执行上述两条命令!!!
# python manage.py makemigrations,将操作记录记录到小本本上,即migration文件夹里
C:\Users\AERO\PycharmProjects\djangoProject>python manage.py makemigrations
Migrations for 'study':
study\migrations\0001_initial.py
- Create model User
# 将操作真正同步到数据库
C:\Users\AERO\PycharmProjects\djangoProject>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, study
Running migrations:
Applying contenttypes.0001_initial... OK
3.3、字段增删改查
增
当在已有数据的表中新增字段时,会提示立即给默认值还是退出手动指定,也可以在创建时指定null=True,还可以直接设置默认值default='XXXX'。
# 我在上面的表基础上添加host字段,如果不设默认值会提示,设置了就没有
host = models.CharField(max_length=32, verbose_name='主机', null=True)
# C:\Users\AERO\PycharmProjects\djangoProject>python manage.py makemigrations
# Migrations for 'study':
# study\migrations\0002_user_host.py
# - Add field host to user
# C:\Users\AERO\PycharmProjects\djangoProject>python manage.py migrate
# Operations to perform:
# Apply all migrations: admin, auth, contenttypes, sessions, study
# Running migrations:
# Applying study.0002_user_host... OK
修
直接改,再执行那两条命令!
# 我把host改成hostname
hostname = models.CharField(max_length=32, verbose_name='主机', null=True)
# C:\Users\AERO\PycharmProjects\djangoProject>python manage.py makemigrations
# Did you rename user.host to user.hostname (a CharField)? [y/N] y
# Migrations for 'study':
# study\migrations\0003_auto_20210214_1028.py
# - Rename field host on user to hostname
# C:\Users\AERO\PycharmProjects\djangoProject>python manage.py migrate
# Operations to perform:
# Apply all migrations: admin, auth, contenttypes, sessions, study
# Running migrations:
# Applying study.0003_auto_20210214_1028... OK
删
直接注释相关代码或者删除代码再执行那两条命令,里面的数据也全没了,一定要慎重操作。当你离开你的工位后,一定要锁屏!
# hostname = models.CharField(max_length=32, verbose_name='主机', null=True)
# C:\Users\AERO\PycharmProjects\djangoProject>python manage.py makemigrations
# Migrations for 'study':
# study\migrations\0004_remove_user_hostname.py
# - Remove field hostname from user
# C:\Users\AERO\PycharmProjects\djangoProject>python manage.py migrate
# Operations to perform:
# Apply all migrations: admin, auth, contenttypes, sessions, study
# Running migrations:
# Applying study.0004_remove_user_hostname... OK
查
你models里面定义的类就是字段啦,还看什么!
3.4、数据增删改查
增
比如在视图函数中,书写对应代码
from study import models
# 第一种添加数据的方式
user_obj = models.User.objects.create(username='kristal', password='666')
# 第二种添加方式
user_obj = models.User(username='andy', password='777')
user_obj.save()
查
查数据也有两种方式,分别是filter和object方法,返回值可以先看成是列表套数据对象的格式,它也支持索引取值,然后切片操作,但是不支持负数索引。
其实这两种都是一样的,取值也是同样的方式:索引+字段名,区别只是第二种作者封装了first方法而已。
# 等同于select * from User where username='sanxi',如果不写条件则意味着select * from User
user_obj = models.User.objects.filter(username='chrystal')
# 第二种方式,列表套对象,支持用索引取值或者作者封装的方法
result = models.User.objects.all()
print(result.first()) # 取对象中的第一个值,或者直接跟上字段名。
改删合并在数据展示实验里
3.5、数据展示实验
先将数据库中的数据用locals将本地所有名称空间回传给前端,用Django提供的封装好的for循环把数据拿出来全部展示到前端,然后给每一个数据两个按钮,一个编辑,一个删除。
后端回传名称空间
def index(request):
from study import models
user_dict = models.User.objects.all()
return render(request, 'first.html', locals())
前端拿到后端的名称空间,用for循环将数据全部取出来展示
<body>
<h1 class="text-center">数据展示</h1>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for user_data in user_dict %}
<tr>
<td>{{ user_data.id }}</td>
<td>{{ user_data.username }}</td>
<td>{{ user_data.password }}</td>
<td>
<a href="" class="btn btn-primary btn-xs">编辑</a>
<a href="" class="btn btn-danger btn-xs">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</body>
更改数据
编辑页面,用form表单来提交新数据给后端视图函数。
<body>
<h1 class="text-center">编辑页面</h1>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post">
用户名:<input type="text" name="username" value="{{ edit_obj.username }}" class="form-control">
密码:<input type="password" name="password" value="{{ edit_obj.password }}" class="form-control">
<input type="submit" value="更改" class="btn btn-info btn-block">
</form>
</div>
</div>
</div>
</body>
编辑页面对应的视图函数
def edit_user(request):
# 获取编辑的那条数据的id
edit_id = request.GET.get('user_id')
# 如果是post请求
if request.method == 'POST':
# 获取更改后的数据
username = request.POST.get('username')
password = request.POST.get('password')
# 将此前id对应的数据更改为新数据
models.User.objects.filter(id=edit_id).update(username=username, password=password)
return redirect('/index/') # 点击提交后修改数据并返回此前页面
edit_obj = models.User.objects.filter(id=edit_id).first() # 获取用户对象
return render(request, 'edit_user.html', locals()) # 将用户对象等本地所有名称空间传给前端
删除数据
实际运用中真正删除应该有二次确认,这里先不做;删除数据内部其实不是真正的删除,会给数据标识是否被删除,如数据被删仅仅是修改数据的状态为被删除。
def delete_user(request):
# 获取用户想要删除的数据的id值
delete_id = request.GET.get('user_id')
# 筛选出id对应的数据然后直接删除
models.User.objects.filter(id=delete_id).delete()
# 返回此前页面
return redirect('/index/')
3.7、ORM创建表关系
比如图书馆系统中有图书表、出版社表作者表、作者详情表;那么书和出版社是一对多关系,外键字段应建立在多的一方;图书和作者是多对多关系,需要创建第三张表来专门存储;作者与作者详情表是一对一关系。
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
class Book(models.Model): # 创建表关系,先将基表创建出来,然后再添加外键字段,默认级联更新级联删除
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2) # 小数总共八位,小数点后面最多两位
"""
图书和出版社是一对多,并且书是多的一方,外键放这
"""
# 默认就是与出版社表的主键字段建立外键关联,如果字段对应的是FK,ORM会自动在字段的后面加_id;如果你自己加了_id,ORM还会再加_id
publish = models.ForeignKey(to='Publish', to_field='id')
"""
图书和作者是多对多关系,外键在任意一方均可,建议是查询频率较高的一方
"""
# 这个字段是虚拟字段,主要用来告诉orm,书籍表和作者表是多对多关系,让orm自动帮你创建第三章关系表
authors = models.ManyToManyField(to='Author')
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
# 作者与作者详情是一对一,可在任意一方,建议在查询频率较高的一方;也会自动加_id
author_detail = models.OneToOneField(to='AuthorDetail')
class AuthorDetail(models.Model):
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=32)