Django

什么是ORM

ORM即对象关系映射,他是一种基于关系型数据库的程序技术,ORM允许使用类和对象对数据库进行操作,提高了对数据库的控制,避免了直接使用sql语句对数据库进行操作.

image-20220419145755689

orm把类映射成数据库中的表,把类的一个实例对象映射成了数据库中的数据行,把类的属性映射成了表中的字段,通过对象的操作对应到数据库表的操作,实现了对象到sql,sql到对象的准换过程

image-20220419150017360

模型类

模型类本质上属于一个python类,只不过在django中称为模型类,他是有django.db.models.Model派生出的子类,在Django中模型类是数据交互的接口,一个模型类代表数据库中的一张数据表,模型类中每一个类属性都代表数据表中的一个字段

定义数据表

from django.db import models
class UserInfo(models.Model):
name = models.CharField(max_length=100)
password = models.CharField(max_length=100)
  • 使用from django.db improt models导入了models模块
  • 使用class关键字对userinfo表进行类定义,并继承了models模块中的model类
  • 数据表中的字段name和password是userinfo类的属性,name和password字段类型都是charfiled,字段长度都是100

orm管理器对象

UserInfo.objects.create(name='jar',password='aaa')

objects是管理器对象,数据库的增删查改可以用他来实现

Obj = UserInfo(name="jar",password="aaa")
Obj.name="john"
Obj.save()

创建userinfo实例对象调用save()保存

UserInfo.objects.all()#查询表中的所有记录
UserInfo.objects.filter(name_contains='j')#查询表中name含有“j”的所有记录,被使用较多
UserInfo.objects.get(name="john")#有且只有一个查询结果,如果超出一个或者没有,则抛出异常
UserInfo.objects.get(name="john").delete()#删除名字为john的记录
UserInfo.objects.get(name="john").update(name='TOM')#更新数据表的name为TOM

auth模块

auth 模块定义了一张名叫 auth_user 的数据表,该表是 auth 模块的内建用户表,开发者调用 auth 模块的相应接口生成此表,auth_user 表的字段以及字段类型

image-20220419151300105

现在新建一张auth_user用户表,并为此表添加一个新用户user.首先用如下方式引入auth模块的User方法

from django.contrib.auth.models import User

通过下面的方法创建新用户User

user = User.objects.create_user(username='c语言中文网',password='123456',email='664104694@qq.com')
save()#调用该方法保存数据

同时也可以使用如下方法修改密码

user.set_password(password='12345abc')#会对原密码进行修改

auth模块也提供了认证用户功能,可以用下面的方式引入后使用

from django.contrib.auth improt authenticate

然后使用关键字传参的方式来传递用户凭证,从而达到用户认证的目的

user = authenticate(user='wanan',password='wanan')

auth应用模块的其他作用

auth模块还实现一些其他功能

  • 用户的登录(login) 退出(logout)功能 封装在django.contrib.auth里面
  • 用户权限系统封装在django.contrib.auth.models.Permiassion中,可以对用户的权限进行增加 修改 删除
  • 用户组可以用过 from django.contrib.auth.models.Group 导入后来创建组或者删除组
user.user_permission.add(permission)#给某个用户权限的添加权限
group = Group.objects.create(name=group_name)#添加新的用户组
group.save() #保存新建好的用户组
group.delete()#删除用户组

auth模块提供的主要功能

  • 实现并维护了用户与用户组的增加 删除 更改功能
  • 实现了用户权限与用户组权限的删除 增加 更改
  • 实现了可以自定义用户权限和用户组权限功能

了解Django后台管理功能

使用下面的命令来创建超级用户

python manage.py createsuperuser

通过此命令来设置用户名 密码和邮箱

视图函数

视图函数是一个python函数或者类,开发者主要通过编写视图函数来实现业务逻辑,视图函数首先接受来自浏览器或者客户端的请求,并最终返回响应,视图函数返回的响应可以是html文件.也可以是http协议中的303重定向

from django.http import Httpesponse
def Hello_my_django(request):
return HttpResponse('<html><body>Hello my Django</body></html>')

httpResponse视图响应类型,从django.http模块中导入HttpResponse.它规定登录视图函数至少有一个参数,第一个参数必须是request,request 是HttpRequest请求类型的对象,它携带了浏览器的请求信息,所以视图函数的第一个参数必须为request.return视图响应,视图函数要返回响应内容,这里的响应内容是我们用HTML标签编写的,把它作为HttpRespose的对象返回给浏览器

模板系统

虽然上面的函数能够顺利完成响应任务,没有使用模板.

当创建好易购django项目后,我们可以在项目的同级目录下创建一个templates文件夹,对它进行简单的配置之后,这个文件夹将被Django自动识别

我们的templates文件夹中新建一个HTML文件,并且将此文件命名为hello.html,然后在文件中书写

<html><body>{{vaule}}</body></html>

写视图函数

from django.shortcuts import render
def hello_my_diango(request):
return render(request,'hello.html',{"value":"hell my Django"})

模板传参

htllo.hmtl文件中的是一个模板的变量,视图函数必须把数据形成字典的形式才可以传递给模板,这就是”模板传参”

render方法

render是view层加载模板的一种方法,它封装在django.shortcuts模块中,render方法使用起来非常方便,它首先加载模板,然后将加载完成的模板响应给浏览器

django路由系统应用

一个用户像web站点发送请求,是用过url实现的,当web服务器端接受到用户请求后,它又是怎么处理的呢,

django.conf.urls中封装了路由模块,先进的django项目中提供了urls.py(创建项目后自动生成的配置文件)路由配置文件,urls.py文件中定义了一个urlpayyerns的列表,他是url()实现对象组成的列表,

from django.conf.urls import url
urlpatterns = [
url('^admin/',amdin.site.urls),
...
]

后台admin管理系统的路由就定义在了列表的第一个位置,

url(regex,view,name=None)
  • regex,匹配请求路径,用正则表达式表示
  • view,指定regex匹配路径所对应的视图函数的名称
  • name,是给url地址起一个别名,在模板反向解析的时候使用

配置第一个url实现页面访问

在 urls.py 的同级目录下,新建 views.py 文件,把它作为编写视图函数的 View 层,然后在 views.py 中编写如下代码

from django.http import HttpResponse
def page_view(request):
html='<h1>欢迎来到,C语言中文网,网址是http://c.biancheng.net</h>'
return HttpResponse(html)

假如现在有一个名叫 “myject”的 Django 项目,首先需要在 urls.py 文件中导入 views.py, 这么做的目的是把 URL 与视图层进行绑定,然后在 urls.py 的 urlpatterns 中编写如下代码

from django.conf.urls import url
from django.contrib import admin
from myject import views
urlpatterns = [
url(r'admin/', admin.site.urls),
url(r'^page$/',views.page_view),]
  • 代码前三行对应的是url模块,admin模块,以及视图层views做了导包
  • 路由地址被定义为page,也就是在本机浏览器地址栏输入http://127.0.0.1:8000/page 进行访问views.page_view将 page/ 路径与对应的视图函数进行了关联

正则与正则分组使用

url(r'^page(\d+)',view.page_view)

同时也可以使用正则分组的方式匹配地址

r'^(\d+)/(\w{3})/(\d+)' 匹配类似于 http://127.0.0.1:8000/521/Django/1314的地址

正则捕获组使用

url(r'^person/(?P<name>\w+)/(?P<age>\d{1,2})',views.person_view)

在视图函数层,用函数关键字传参的方法,将 name 与 age 传递给视图函数

def person_view(request,name,age):
s = '姓名: ' + name
s += ' 年龄: ' + age
return HttpResponse(s)

一个分组表示一个参数,多个参数需要使用多个分组,并且使用/隔开

dojango项目配置文件

magngae.py文件

一级目录中的manage,py文件是管理django项目的重要命令行工具.它主要用户启动项目 创建应用和完成数据库迁移等

_init_.py

二级子目录中的_init_.py文件用于表示当前所在目录是一个python包,如果在此文件中,通过import导入其他方法或者包会被Django自动识别

settings.py文件

settings.py文件是Djangp项目的重要配置文件项目启动时,settings.py配置文件会被自动调用,而他定义的一些全局为Django运行提供参数,在此配置文件中,也可以自定义一些变量,用于全局作用域的数据传递

urls.py文件

urls.py文件用于记录Django项目中的url映射关系,他是属于项目的基础路由配置文件,路由系统就是在这个文件中完成相应的配置的,项目中的动态路径必须先经过该文件匹配,才能实现web站点上资源的访问功能

wsgi.py是wsgi(web server gateway interface)服务器程序的入口文件,主要用于启动应用程序负责网络通讯部分的实现,只有在项目部署的时候才会用到他

settings.py文件

base_dir

他用于绑定当前项目的bookstore所在的绝对路径,项目中的所有文件都需要依赖此路径,绑定路径的方法

BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

__file__是python的语法,显示当前文件的位置,os.path.abspath(__file__)方法返回当前文件的绝对路径

SECRET_KEY

这个变量的本质是一个加密的盐,它一般配合加密算法Hash MD5一起使用.例如用户密码的加密或者简历会话时用到的sessionid都需要使用SECRET_KEY 在实际的开发中,一般将它保存在系统的环境变量中以企鹅包加密盐的安全

DEBUG

用于配置Django项目的启用模式

  • DUBUG = True用于在开发环境中使用,属于调试模式,在项目的运行中会暴露一些错误信息以方便调试
  • DEBUG = False用于线上环境,表示不启用调试模式

ALLOWED_HOSTS

用于配置能够访问当前站点的域名,当DEBUG =Fales时必须填写

  • [] 空列表,表示只有127.0.0.1可以访问
  • [‘*’] 表示任何网络都能访问
  • [‘192.168.1.3’, ‘192.168.3.3’] 表示只有当前两个主机能访问当前项目

INSTALLED_APPS

这个参数是指当前项目中用来安装的应用的列表,dgango把默认自带的应用都放在了这个列表里面,比如admin后台应用,auth用户管理系统等,

比如公司要单独开发一个后台管理系统,就可以把第一项 admin 注释掉。开发时自己编写的应用都必须在这个变量表中进行注册才能生效。所以这个列表需要经常的改动

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

MIDDLEWARE

它用于注册中间件,我们在《Django中间》中进行了介绍,Django 默认加载了一些中间件。例如,用于处理会话的 SessionMiddleware 等,同样我们可以对这些中间件进行添加或者注释。

ROOT_URLCONF

ROOT_URLCONF = 'BookStore.urls'

它指定了当前项目的根url,是django路由系统的入口

TEMPLATES

它用于指定模板的配置信息,列表中每一个元素都是一个字典,

{'BACKEND':'django.template.backends.django.DjangoTemplates'

WSGI_APPLICATION

WSGI_APPLICATION = 'BookStore.wsgi.application'

项目部署时,django内置的服务器将使用wsgi应用程序对象的完整python路径

DATABASES

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

它用于指定数据库的配置信息,这里默认配置是django的sqlite3

AUTH_PASSWORD_VALIDATORS

这是一个支持插拔的密码验证器,且可以一次性配置多个,Django 通过这些内置组件来避免用户设置的密码等级不足的问题。

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]

LANGUAGE_CODE和TIME_ZONE

分别代表语言配置项和当前服务端时区的配置项,我们常用的配置如下所示:

LANGUAGE_CODE 取值是英文:'en-us'或者中文:'zh-Hans';
TIME_ZONE 取值是世界时区 'UTC' 或中国时区 'Asia/Shanghai'。

USE_118N和USE_L10N

项目开发完成后,可以选择向不同国家的用户提供服务,那么就需要支持国际化和本地化。USE_118N 和 USE_L10N 这两个变量值表示是否需要开启国际化和本地化功能。默认开启的状态。

提示:USE_I18N = True 与 USE_L10N = True 其的 I18N 指的是国际化英文缩写,L10N 指的是本地化英文缩写。

USE_TZ=True

它指对时区的处理方式,当设置为 True 的时候,存储到数据库的时间是世界时间 ‘UTC’

STATIC_URL= ‘/static/‘

它指的是静态资源的存放位置,静态资源包括 CSS、JS、Images。比如我们要在项目中添加一些图片,通常这些静态图片被存放在新建的 static 目录下,这样就实现了通过 STATIC_URL= ‘/static/‘ 路径对静态资源的访问。

创建应用

一个app就是一个python包,通常一个app可以包含模型 视图模板和url配置文件,可以被应用到多个django项目中,因为他们的本质就是可被重用的python软件包

创建一个app

python manage.py startapp index
├─ admin.py
├─ apps.py
├─ models.py
├─ tests.py
├─ views.py
├─__init__.py

└─ migrations
├─__init__.py
```

- admin.py 用于将model定义的数据表注册到管理后台,是django admin应用的配置文件
- apps.py用于应用程序本身的属性配置文件
- models.py用于定义应用中所需要的数据表
- tests.py文件用于编写当前应用陈旭的单元测试
- views.py用来定义视图处理函数的文件
- 一级目录下的\__init__.py文件标识index应用是一个python软件包
- migrations目录用于存储数据库迁移时产生的文件

应用的添加

INSTALLED_APPS 做了介绍,把我们创建的应用添加到这个列表

```
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
]
```

用如上的方法添加完成后,

```
提示:添加应用到 settings.py 中,这个操作看似非常简单,但是初学者却容易忽略或者忘记,所以大家在学习 Django 的过程中一定要注意细节。
```

## 模板加载与响应

模板的配置

在settins.py中有一个templates变量

```
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], #指定模板文件的存放路径
'APP_DIRS': True, #搜索APP里面的所有templates目录
'OPTIONS': {
'context_processors': [ #context_processors 用于配置模板上下文处理器
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
```

- BACKED:bjango默认设置,指定了要是用的模板引擎的python路径
- DIRS 一个目录列表,指定模板文件的存放路径,可以是一个或者多个.模板引擎将按照列表中定义的顺序查找模板文件
- APP_DIRS 一个布尔值,默认为True 表示会在安装应用中的templates目录中搜索所有模板文件
- OPTIONS 指定额外的选项,不同的模板引擎有着不同的可选参数,例如content_pricessors用于配置模板上下文处理器,在使requestcontext时将看到他们的作用

修改settings配置文件

修改 settings.py 文件,设置 TEMPLATES 的 DIRS 值来指定模板的搜索目录为“templates”

```
'DIRS': [os.path.join(BASE_DIR, 'templates')]
```

模板的加载与响应方式

通过loader获取模板,通过httpresponse进行响应

```
from django.template import loader
# 1.通过loader加载模板
t = loader.get_template("模板文件名")
# 2.将t转换成HTML字符串
html = t.render(字典数据)
# 3.用响应对象将转换的字符串内容返回给浏览器
return HttpResponse(html)
```

通过render方法直接加载并响应模板

```
from django.shortcuts import render
return render(request,'模板文件名', 字典数据)
```


orm进阶应用

定义数据表

下面我们使用orm定义index应用所需要的数据表,首先找到models.py

from django.db import models
class Book(models.Model): #创建book表
title = models.CharField(max_length=30,unique=True,verbose_name='书名')
public = models.CharField(max_length=50,verbose_name='出版社')
price = models.DecimalField(max_digits=7,decimal_places=2,verbose_name='定价')
def default_price(self):
return '$30'
retail_price = models.DecimalField(max_digits=7,decimal_places=2,verbose_name='零售价',default=default_price)
def __str__(self):
return "title:%s pub:%s price:%s" % (self.title, self.public, self.price)

class Author(models.Model):#创建作者表
name = models.CharField(max_length=30,verbose_name='姓名')
email = models.EmailField(verbose_name='邮箱')
def __str__(self):
return '作者:%s'%(self.name)

class UserInfo(models.Model):
username = models.CharField(max_length=24,verbose_name='用户注册')
password = models.CharField(max_length=24,verbose_name='密码')

通过上面的代码,我们定义了一个名叫Book的数据表,数据表由以下字段构成书名(title)、出版社(public)、价格(price)、零售价(retail_price),而且对每个字段都做添加了相应的字段属性以及字段选项。

filed的通用字段选项

model中添加的字段都是field类型的实例,不同的field类型可能会支持不同的字段选项,但是也有很多字段选项是通用的,即可以用任何一种field类型中,这里介绍以下常用且重要的通用字段选项,他们都有对应的默认值,这些字段选项都是可选的

blank

默认值是False,设置为True时,字段可以为空,设置为false时,字段是必须填写的,如果是字符型字段charfield和textfield,他们使用空字符串来存储空值的.

unique

默认值是false,他是一个数据库级别的选项,规定该字段在表中必须是唯一的

数据库层面对待唯一性约束会创建唯一性索引,所以,如果一个字段数额孩子unique=true就不需要对这个字段加上索引选项了.

null

默认为false,如果此选项为false建议加入default选项来设置默认子,如果设置为true,表示改列值允许为空.日期型,时间型以及数字型字段不接受空字符串,所以当设置integerfield,datetimefield型字段可以为空时,需要将blank与null均设置为true才可以的,

对于charfiled和textfiled这样的字符串类型,null字段应该设置为false,如果为true,对于空数据就会有两种概念

db_index

默认值是false,如果设置为true,django则会为该字段创建数据库索引,如果该字段经常作为查询的条件,那么就需要设置db_index选项,从而加快数据的检索速度

db_column

这个选项用于设置数据库表字段的名称,如果没有指定,django默认使用model中字段的名称

default

用于给字段设置默认值,这个选项可以设置为一个值或者是一个可以调用的对象,但不能是可变的对象,不同字段类型的默认值也不同,比如booleandiled布尔类型default值为ture或者false,主要使用场景是当一个字段的值被用户省略时,后台服务器自动为该字段的设置默认值

primary_key

默认值是false,如果设置为true,表示该字段为主键,在django中默认id为主键,也就是说即使你的数据表中没有创建id字段,django也会自动为你创建id字段并将其设置为主键,如果你在表中设置了其他字段为主键时,那么django将取消为id字段设置为主键

choices

这个选项用于给字段设置可以选择的值,他是一个可以迭代的对象,即列表或者元组,其中每一个元组都是一个二元组(a,b)的形式,a是用来选择的对象,b是对a的描述信息,

from django.db import models
class UserInfo(models.Model):
#定义chocies参数的对应关系,以元组或者列表的形式进行描述:
choices = (
('male','男性'),
('female','女性'),
)
gender = models.CharField(max_length=2,choices= choices,default='male')

verbose_name

设置此字段在admin后台管理系统界面上的显示名称,如果没有设置改字段,django将会之间展示字段名并且将字段名中的下划线转变成空格

Meta元数据类属性解析

meta内部类

每一个模型类(Model)下都会有一个子类meta,这个子类就是定义元数据的地方,meta类封装了一些数据库的信息,称为model的元数据,django会将meta中的元数据选项定义附加到model中,常见的元数据定义有db_table(数据表名),abstract(抽象类) ,ordering(字段排序)等,meta作为内部类,它定义的元数据可以让admin管理后台对人更加友好.

meta定义的元数据相当于model的配置信息,所以我们可以根据自己的需求进行选择行的添加.当没有需要的时候也可以不定义meta,增时候django会应用默认的meta元数据

meta类元数据

abstract

一个布尔类型的变量,这个属性是定义当前的模型是不是一个抽象类,所谓抽象类是不会对应数据库的表的.一般我们用他来归纳一些公共属性的字段,然后继承他的子类可以继承这些字段.如果abstract =True这个model就是一个抽象类

ordering

用于执行获取对象列表时的排序规则,它是一个字符串的列表或者元组对象,它的使用格式是由代表字段的字符串和一个表明降序的 - 构成.当字段名前面没有- 时,将默认使用升序排列,使用?将会随机排列.

ordering['add_time'] #按照升序排序
ordering['-add_time'] #按照降序
ordering['?add_time'] #随机排序
#同时指定多个字段来进行排序
ordering['add_time','-last_login_time']#先按升序,在按降序

verbose_name_plural

这个元数据主要用在管理后台的展示上面,verbose_name_plural是模型类的复数名,如果不设置的话,django会使用小写的模型名作为默认值,并且在结尾加上s.通过此项元数据设置可以去掉s

db_table

这个字段用于指定数据表的名称,通常没有特别的需求,将按照django默认的规则生成model对应的数据库表名.

#定义改model在数据库中的表名
db_table = "Students"
#使用自定义的表名,可以通过以下属性
table_name = 'my_owner_table'

app_lable

这个选项只在一种使用情形,就是你的模型不在默认的应用程序包下的models.py文件中,这个时候需要指定你这个模型是那个应用程序的app_label = ‘app_name’

managed

他是一个布尔类型的变量,默认为true,代表django会管理数据的生命周期,即使用django提供的syncdb和reset命令可以完成创建和删除数据表,如果为False,则不会对此模型执行数据库表的创建或者删除操作,比如数据表之间存在manytomany的关系,在指定为managed=false的情况下django不会自动创建中间数据表,需要我们自己手动创建.

indexs

他是一个列表类型的元数据项,用来定义model的索引,列表中的每一个元素都是index类型的实例

index引自 django.db.models.indexes.index

default_permissions

django默认会给每一个定义的model设置三个权限即添加删除更改,它使用的格式

default_permissions = ('add','change','delete','view')

permissions

除了django默认给model添加的三个权限之外,还可以通过permissions给model添加额外的权限,不过permissions是一个包含二元组的元组,或者列表,所以使用的时候要注意格式,即

permiassions=[('have_read_permission','有读的权限')]

unique_together

这个选项用于下面的情形,当你需要通过两个字段保持唯一性时使用.比如用户的名称和身份证号码,两者的组合必须是惟一的,那么需要这样设置

unique_togeher=(('first_name','last_name'),)

一个manytomanyfield不能包含在unique_togeher中,如果你需要验证manytomanyfield字段的唯一验证,尝试使用through属性进行关联.

proxy

默认值为flase,如果设置成ture则表示为基类父类的代理模式,主要是用于创建父模型的代理模型

db_tablespace

表空间,用于优化数据库性能,

get_lastest_by

指定一个datafield或者datetimefield字段的名称,即model的属性名称

get_lastest_by='order_date'

这个设置让你在使用模型管理器的lastest()方法时,默认使用order_date指定字段来排序

model三种继承模型的详解

django中的每一个model都是一个python类,model继承自django.db.models.model,通过类之间的继承,django会对自定义的model自动添加了两个属性分别是id和objects

在mdoel不指定主键的情况下,django会通过autofiled字段类型将id设置为默认自增主键,

bojects查询管理器

object是manager类的实例对象,被称为查询管理器,是数据库查询的入口,每一个django model都至少有一个manager实例,可以通过自定义创建manager以实现对数据库的定制访问,这里我们讲到manager类,它也同样定义在models模块中

django.db.models.Manager

model的继承模型

django model的继承与python类的继承是一样的,只是django要求所有自定义的model都必须继承自django.db.models.Model,在django中model之间有三种继承模型,他们分别是抽象基类,多表继承以及代理模型

抽象基类

抽象类继承的作用是将子表中通用的字段聚合在一起,并将这些字段统一定义在抽象基类中,避免于重复定义这些字段.抽象基类的定义通过在模型的meta中定义属性abstract=True来实现.

from django.db import models
class AbstractBase(models.Model):
id = models.AutoField()
content = models.CharField(max_length=100)
username = models.CharField(max_length=80)
nowday = models.DateTimeField()
class Meta:
abstract = True

class SomeThing(AbstractBase):
testexams = models.CharField(max_length=50)
class SomeComment(AbstractBase):
level = models.CharField(max_length=20)

这里的三个类映射到数据库后,但会被定义为两个数据表,分别是SomeThing 与 SomeComment他们都继承自AbstractBase,且继承了父表中的所有字段值,同时自身又定义了一个新的字段,所以,他们对应的字段分别

  • SomeThing 数据表:有 id、content、username、nowday、testexams 等 5 个字段;
  • SomeComment 数据表:有 id、content、username、nowday、level 等 5 个字段。

关于model的元数据继承关系

  • 抽象基类中定义的元数据,子类中没有定义,子类会继承基类中的元数据
  • 抽象基类中定义的元数据,子类也定义了,子类优先级更高
  • 子类可以定义自己的元数据,即不出现在抽象基类中的元数据

在定义抽象基类时,需要注意,如果定义了foreignkey或者manytomanyfield类型的字段,并且设置了related_name或者related_query_name参数,由于继承关系,子类也会拥有同样字段,所以在子类中的反向名称和查询名称是唯一的

多表继承

这是django支持的第二种继承方式,因为每一个类都是一个完整的model,而不属于抽象基类,所以父model和子model都有数据库表,而且django默认都会给和字表和父表之间自动创建一个onetoonefield数据表关,并且改字段将作为字表的主键.

from django.db import models
class a(A):
testname = models.charFiled(max_length=255,help_text="测试")

如果你想指定链接父类的属性名称,你可以创建你自己的onetoonefield字段,并且设置parent_link=True从而使用该字段链接父类

多表继承与抽象基类有一个显著的不同点是meta内部类的继承,子类不会继承父类的meta定义,但是,有两个meta元数据项比较列,他们是ordering和get_lastest_by,他们是会被子类继承的,所以,如果不想让他们影响子类的行为,应该覆盖着两个元选项,比如父类有了排序设置,而你并不像让子类有任何排序设置,你可以使用如下方式来禁用子类的排序

class ChildModelName(ParentModelName):
class Meta:
ordering = []字表不会排序

代理模型

代理模型用来给父model添加一些方法或者修改器meta选项,但是父model的字段定义不会被修改,我们可以理解为对原父model进行了copy,而被copy出来的model就叫父model的代理模型,但是这个代理模型又有其自己的特点,这相当于python面向对象中的类继承与多态

这里需要注意的是代理模型不会在数据库汇总创建新的数据表,它将使用父model的数据表,即对代理模型的CURD操作将会作用到原始的model中

class BookExtend(Book):
class Meta:
ordering=['id']#定义meta选项顺序排序按照id字段
proxy = True #设置代理模型
def __str__(self):
return 'title'

添加完上述代码,然后执行数据库迁移操作。通过查看 MySQL 数据库可以看到并没有新建 BookExtend 数据表

实现数据表数据插入

save()方法创建model实例

django为创建model实例提供了两种方法,一种是直接调用model的save方法,另一种是用过对象管理器(objicts manager)的create方法,这两种方法都可以实现创建model实例对象,

book = Book(title="python", public='a', price='59.00', retail_price='59')  # 创建book实例
book.save() # 调用save方法进行保存

每创建一条数据都需要调用一个save()方法,save()方法还可以保存已有对象更改后的信息

book.title='java'
book.save()

create方法创建model实例

还可以使用管理器对象提供的create()方法

Book.objects.create(title='java',public='a',price='20',r)