更多ORM的语法参见:https://www.cnblogs.com/wupeiqi/articles/6216618.html
一.ORM(Object Relational Mapping;对象关系映射)
- Django内置的ORM只能用于Django的语法
1.功能:用于实现面向对象语言里不同类型系统的数据间的转换,也就是用面向对象的方式操作数据库
- 1个类对应1个表,1个实例对应1条记录
2.优点:
·使得与通用数据库的交互简单易行,而且完全不用考虑SQL语句,从而实现快速开发
·数据库搬迁更简单(无需更改代码,只需更改数据库配置)
·可以一些SQL语句带来的性能问题
#实例:查询User表中的所有字段(见下图)
如使用select * from auth_user就会因多了匹配动作而降低效率
3.缺点:
·性能有所牺牲;不过现在的各种ORM框架都在尝试各种方法,如缓存/延迟加载登,来减轻这个问题,效果很显著
·对个别复杂查询仍力不从心;为解决这个问题,ORM一般也支持写raw sql
·通过QuerySet的query属性查询对应操作的SQL语句
author_obj=models.Author.objects.filter(id=2)
print(author_obj.query)
4.表与表之间的关系:
on_delete参数参见:https://www.cnblogs.com/tuifeideyouran/p/4418450.html
1.一对一(One-to-One):员工与工号
#主要用于不常用字段的独立放置
#在一对多的关系的基础上加上UNIQUE=TRUE的约束
#当2个类之间有继承关系时,默认会创建1个一对一字段
#字段创建:
<field>=models.OneToOneField(to=None,on_delete=None[,to_field=foreign_key])
#参数说明:
to:要关联的表名;也可以是位置参数
to_field:要关联的字段名
on_delete:指定级联删除策略(可选值见下)
field:在本表中的字段名
#on_delete可选值:
on_delete=models.CASCADE:删除关联数据时,与之关联的记录也删除
on_delete=models.DO_NOTHING:删除关联数据时,引发错误IntegrityError
on_delete=models.PROTECT:删除关联数据时,引发错误ProtectedError
on_delete=models.SET_NULL,:删除关联数据时,与之关联的值设为null(需要可为空)
on_delete=models.SET_DEFAULT:删除关联数据时,与之关联的值设为默认值(需要有默认值)
on_delete=models.SET(<value>):删除关联数据时,与之关联的值设为指定值value
on_delete=:models.SET(<可执行对象>):删除关联数据时,与之关联的值设为可执行对象的返回值
##############################################################################
2.一对多(One-to-Many;最常用):员工与部门
#利用FOREIGN KEY
#字段创建:
<field>=models.ForeignKey(to=None,on_delete=None[,to_field=primary_key,\
related_name=None,related_query_name=None,limit_choices_to=None,\
db_constraint=True,parent_link=False])
#参数说明:
to:要关联的表名;也可以是位置参数
#可省略" ",但此时for_tab必须在本表上方(不加按变量找,加则按映射关系找)
to_field:要关联的字段;默认为for_tab的主键
on_delete:指定级联删除策略(可取值见下)
可为:CASCADE/PROTECT/SET_NULL/SET_DEFAULT/SET( )/DO_NOTHING
#从1.9开始必需
related_name:反向操作时使用的字段名,用于代替[<tab_name>_set]
#详情参见 Model2.三.3.对象形式的反向查找 部分
related_query_name:反向操作时,使用的连接前缀,用于替换[<tab_name>]
limit_choices_to=None:在Admin/ModelForm中显示关联数据时,提供的条件
如:limit_choices_to={'nid__gt':5}或limit_choices_to=lambda:{'nid__gt':5}
db_constraint:是否在数据库中创建外键约束
#如为False,数据库中没有约束,但Foreign Key的其他功能都被保留
parent_link:在Admin中是否显示关联数据
field:在本表中的字符名,Django自动将字段名变为<field>__<pri_key>
#实际使用需要使用<field>__<pri_key>
##############################################################################
3.多对多(Many-to-Many):作者与书籍
#转换成2个一对多的关系(自动创建第3张表进行关联,这张表不能通过ORM添加记录)
#自动生成的第3张表只能包含3个字段:另外2个表的主键和1个AutoField
#当然也可以自己创建第3张表(两个foreign key)
#字段创建:
<field>=models.ManyToManyField(to=None[,related_name=None,related_query_name=None,\
limit_choices_to=None,symmetrical=None,through=None,through_fields=None,\
db_constraint=True,db_table="<tab>_<to>"])
#参数说明:其他参数同.ForeignKey()
symmetrical:用于指定内部是否创建反向操作的字段(仅用于多对多自关联时)(详情见下)
through:指定某表作为多对多关系中的第3张表;为str
through_fields:指定through中的哪些字段作为关联表;为str list(示例见下)
#如果同时指定上述2个参数,ManyToManyField的.add()/.remove()/.clear()/.set()将无法使用,但.filter()/.all()可以继续使用
db_table:自动创建的第三张表在数据库中的名称;默认为<本表名>_<关联表名>
##############################################################################
4.自关联:
(1)互粉(多对多):博主和粉丝都是用户
class User(models.Model):
userid=models.AutoField()
username=models.CharField(max_length=32,db_index=True)
d=models.ManyToManyField("User",related_name="u")#"User"也可以换成self
#涉及到自关联时一定要设置related_name,否则反向操作时会出问题
(2)评论区(一对多):可以回复评论
class Comment(models.Model):
pid=models.AutoField(primary_key=True)#评论的ID
content=models.TextField()#评论的内容
news_id=models.ForeignKey(News,ob_delete=models.CASCADE)
#新闻的ID,表示:是哪条新闻下的评论
user_id=models.ManyToManyField(User)#用户的ID,表示:是哪个用户的评论
reply_id=models.ForeignKey(Comment,ob_delete=models.CASCADE,releted_name="ri")
#表示:回复的是哪条评论;为0表示不是回复
- 关于symmetrical参数:
做如下操作时,不同的symmetrical会有不同的可选字段:
models.BB.objects.filter(...)
1.当symmetrical=True,可选字段有code/id/m1
class BB(models.Model):
code=models.CharField(max_length=12)
m1=models.ManyToManyField('self',symmetrical=True)#self表示和自身关联
2.当symmetrical=False,可选字段有BB(表名)/code/id/m1
class BB(models.Model):
code=models.CharField(max_length=12)
m1=models.ManyToManyField('self',symmetrical=False)
- through_fields参数示例:
from django.db import models
class Person(models.Model):
name=models.CharField(max_length=50)
class Group(models.Model):
name=models.CharField(max_length=128)
members=models.ManyToManyField(
Person,
through='Membership',
through_fields=('group','person'),
)
class Membership(models.Model):
group=models.ForeignKey(Group,on_delete=models.CASCADE)
person=models.ForeignKey(Person,on_delete=models.CASCADE)
inviter=models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason=models.CharField(max_length=64)
二.数据库的配置
1.Django默认支持SQLite,MySQL,Oracle,PostgreSQL数据库
(1)SQLite:
·Django默认使用SQLite的数据库(见下图),默认自带SQLite的数据库驱动
·引擎名称:django.db.backends.sqlite3
(2)MySQL:
·引擎名称:django.db.backends.mysql
·MySQL的驱动程序:
MySQLdb(Python2中使用,对Python3的支持不好)
MySQLClient
MySQL
PyMySQL(纯Python的MySQL驱动程序)
2.更改数据库:
修改settings.py中的DATABASES设置,将ENGINE改为指定数据库的引擎
3.其他数据库设置:
#settings.py中的DATABASES设置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'books',
'USER': 'root',
'PASSWORD': '',
'HOST': '',
'PORT': '3306',
}
}
#参数说明:
NAME:数据库的名字
在连接MySQL前该数据库必须已在MySQL中创建
而项目文件夹中的db.sqlite3数据库由项目自动创建(见下图)
USER:数据库的用户名
PASSWORD:数据库的密码
HOST:数据库主机IP,留空则为localhost
PORT:数据库端口
设置完成后,在启动Django项目前,需要在MySQL创建数据库
然后启动项目,这次会报错:no module named MySQLdb
这是因为Django默认的驱动是MySQLdb,这里需要的是PyMySQL
需要在项目文件夹下同名文件夹中的__init__.py里写入(见下图):
import pymysql
pymysql.install_as_MySQLdb()
4.在Pycharm中查看数据库内容(以SQLite为例):
- SQLite数据库在当前文件夹中(见上图);MySQL数据库在MySQL中
右侧Database栏-+栏-Data Source栏-选择数据来源
配置连接那个数据库-选择Apply
把当前文件夹内的数据库引擎拖到右侧的数据来源栏处
选中表查看
可通过"+"选项创建记录,通过"-"选项删除选定的记录
三.Admin管理工具
runoob.com/django/django-admin-manage-tool.html
1.简介:
Admin是Django提供的基于Web的数据库后台管理工具;可从数据库读取数据,并在线进行管理
如果不需要十分复杂的功能,默认配置已经足够使用;但一些特殊功能(如搜索功能)需要定制
是django.contrib的一部分,可以在项目的settings.py中的INSTALLED_APPS里找到:
#django.contrib是一套庞大的功能集,是Django基本代码的组成部分
INSTALLED_APPS=(
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)
如果想使用中文界面,可以在setting.py中修改LANGUAGE_CODE:
英文界面:LANGUAGE_CODE = 'en-us'
中文界面:LANGUAGE_CODE = 'zh-hans'
2.激活:
通常在创建项目时会在urls.py中自动设置好,只需去掉注释即可使用:
#urls.py中
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
3.使用
(1)登录:
需要先在使用的数据库中创建账号
或在终端里创建超级用户:
>>> python manage.py createsuperuser
Username (leave blank to use 'root'):
Email address:
Password: #输入后也不显示
Password (again): #输入后也不显示
Superuser created successfully.
默认登录界面:IP:port/admin#见下图
登录后进入管理界面(如果有相应权限)#见下图
(2)注册Model到Admin:
为了让Admin管理某个Model,需要先注册其到Admin
1.使用register的方法:
#在应用文件夹下的admin.py中:
from django.contrib import models
admin.site.register(models.Book)
admin.site.register([models.Book,models.Publisher,models.Author])
admin.site.register(models.Book,MyAdmin)
2.使用register的装饰器:
#在应用文件夹的models.py中:
@admin.register(Book)
class MyAdmin(admin.ModelAdmin):#自定义管理界面的类
pass
4.自定义管理界面:
(1)ModelAdmin:
#ModelAdmin:
admin.ModelAdmin:管理界面的定制类,要自定义管理界面需继承该类
#auth系统:
Django自带的登录认证系统
Django admin默认使用auth系统进行登录认证
(2)一些常用设置:
list_display=("<field1>","<field2>"...):指定要显示的字段
#默认不能包括多对多字段
search_fields=("<field1>",...):指定可搜索的字段
#默认不能包括多对多字段
list_editable=("<field1>",...):指定可编辑的字段
#主键无法编辑
list_filter=("<field1>",...):指定列表过滤器
#跨表时不需要通过"__",直接写字段名即可
filter_horizontal=("<field1>",...):可以通过搜索添加
#filter_vertical=("<field1>",...):类似filter_horizontal()
list_per_page=<x>:指定每页显示的记录数
ordering:指定排序字段
#实例:
from django.contrib import admin
from app01.models import *
#Register your models here:
#@admin.register(Book)#单给某个表加一个定制
class MyAdmin(admin.ModelAdmin):#自定义管理界面
list_display=("title","price","publisher")
search_fields=("title","publisher")
list_filter=("publisher",)#不加","会被以str的形式传入
ordering=("price",)
fieldsets=[
(
None,
#不折叠,直接显示
{'fields':['title']}
),
(
'price information',
#折叠以下字段,显示为"price information"
{
'fields':['price',"publisher"],
'classes':['collapse']
}
),
]
#以上定义了1个MyAdmin类,用以说明自定义管理界面的显示格式
#以下注册models:
admin.site.register(Book,MyAdmin)#使用自定义的界面显示
admin.site.register(Publish)#使用默认的界面显示
admin.site.register(Author)
(3)注册管理界面:
MyAdmin类对应的是Contact数据模型,需要注册#见下图
在这里插入图片描述