Django1.8.2中文文档:Django1.8.2中文文档

模型类关系

1)一对多关系
例:图书类-英雄类
models.ForeignKey() 定义在多的类中。

2)多对多关系
例:新闻类-新闻类型类 体育新闻 国际新闻
models.ManyToManyField() 定义在哪个类中都可以。

3)一对一关系
例:员工基本信息类-员工详细信息类. 员工工号
models.OneToOneField定义在哪个类中都可以。

多对多示例

# 新闻类型类
class NewsType(models.Model):
# 类型名
type_name = models.CharField(max_length=20)
# 关系属性,代表类型下面的信息
type_news = models.ManyToManyField('NewsInfo') # 新闻类
class NewsInfo(models.Model):
# 新闻标题
title = models.CharField(max_length=128)
# 发布时间
pub_date = models.DateTimeField(auto_now_add=True)
# 信息内容
content = models.TextField()
# 关系属性, 代表信息所属的类型
# news_type = models.ManyToManyField('NewsType')

多对多示例

# 员工基本信息类
class EmployeeBasicInfo(models.Model):
# 姓名
name = models.CharField(max_length=20)
# 性别
gender = models.BooleanField(default=False)
# 年龄
age = models.IntegerField()
# 关系属性,代表员工的详细信息
employee_detail = models.OneToOneField('EmployeeDetailInfo') # 员工详细信息类
class EmployeeDetailInfo(models.Model):
# 联系地址
addr = models.CharField(max_length=256)
# 教育经历
# 关系属性,代表员工基本信息
# employee_basic = models.OneToOneField('EmployeeBasicInfo')

一对一关系示例

重点关注一对多的关系;

模型-关联查询

关联查询-一对多

查询和对象关联的数据

在一对多关系中,一对应的类我们把它叫做一类,多对应的那个类我们把它叫做多类,我们把多类中定义的建立关联的类属性叫做关联属性。
例:查询id为1的图书关联的英雄的信息。

b=BookInfo.objects.get(id=1)
b.heroinfo_set.all()
通过模型类查询:
HeroInfo.objects.filter(hbook__id=1)

例:查询id为1的英雄关联的图书信息。

h = HeroInfo.objects.get(id=1)
h.hbook
通过模型类查询:
BookInfo.objects.filter(heroinfo__id=1)

格式:

由一类的对象查询多类的时候:
  一类的对象.多类名小写_set.all() #查询所用数据
由多类的对象查询一类的时候:
  多类的对象.关联属性 #查询多类的对象对应的一类的对象
由多类的对象查询一类对象的id时候:
  多类的对象. 关联属性_id

通过模型类实现关联查询

关联查询
1.通过模型类实现关联查询时,要查哪个表中的数据,就需要通过哪个类来查。
2.写关联查询条件的时候,如果类中没有关系属性,条件需要些对应类的名,如果类中有关系属性,直接写关系属性。

例:查询图书信息,要求图书关联的英雄的描述包含'八'。

BookInfo.objects.filter(heroinfo__hcomment__contains='八')

例:查询图书信息,要求图书中的英雄的id大于3.

BookInfo.objects.filter(heroinfo__id__gt=3)

例:查询书名为“天龙八部”的所有英雄。

HeroInfo.objects.filter(hbook__btitle='天龙八部')

通过多类的条件查询一类的数据:
  一类名.objects.filter(多类名小写__多类属性名__条件名)
通过一类的条件查询多类的数据:
  多类名.objects.filter(关联属性__一类属性名__条件名)

模型-插入和删除

插入、更新和删除
调用一个模型类对象的save方法的时候就可以实现对模型类对应数据表的插入和更新。
调用一个模型类对象的delete方法的时候就可以实现对模型类对应数据表数据的删除。
插入示例:

# 1.创建bookinfo对象
b = models.BookInfo()
b.btitle = "流星蝴蝶剑"
b.bpub_date = date(1990, 1, 1)
# 2.保存进数据库
b.save()

删除示例:

# 1.获取书籍对象
book = models.BookInfo.objects.get(id=bid)
# 2.删除书籍
book.delete()

模型-自关联

自关联是一种特殊的一对多的关系。
案例:显示广州市的上级地区和下级地区。
地区表:id, atitle, aParent_id;
mysql终端中批量执行sql语句:source areas.sql;

自关联案例

models.py

class AreaInfo(models.Model):
"""地区模型类"""
# 地区名称
atitle = models.CharField(max_length=20)
# 关系属性,代表当前地区的父级地区
aParent = models.ForeignKey("self", null=True, blank=True)
E:\Pycharm\Pycharm_save\cp15\test2>cd booktest

E:\Pycharm\Pycharm_save\cp15\test2\booktest>mysql -uroot -p
Enter password: ****
Welcome to the MySQL monitor. Commands end with ; or \g.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use test1000;
Database changed
mysql> source area.sql

area.html

<h1>地区</h1>
<p>{{ area }}</p> <h1>父级地区</h1>
<p>{{ parent }}</p> <h1>子级地区</h1>
<ul>
{% for child in children %}
<li>{{ child }}</li>
{% endfor %}
</ul>

Views.py

def areas(request):
'''获取广州市的上级地区和下级地区'''
# 1.获取广州市的信息
area = AreaInfo.objects.get(atitle='广州市')
# 2.查询广州市的上级地区
parent = area.aParent
# 3.查询广州市的下级地址
children = area.areainfo_set.all()
# 使用模板
return render(request, 'booktest/areas.html', {'area': area, 'parent': parent, 'children': children})

Urls.py

from django.conf.urls import url
from booktest import views urlpatterns = [
url(r'^areas/$', views.areas), # 自关联案例
]

应注意浏览器中的url后面的’/’。

模型-模型管理器

什么是管理器?

BookInfo.objects.all()->objects是一个什么东西呢?
答:objects是Django帮我自动生成的管理器对象,通过这个管理器可以实现对数据的查询
objects是models.Manger类的一个对象。自定义管理器之后Django不再帮我们生成默认的objects管理器。

自定义管理器

可以在BookInfo下自定义一个 book = models.Manager()
这时就不能使用 BookInfo.objects.xxx了,而是BookInfo.book.xxx,但这样并没有什么用。
我们一般这样用:

  • 1)自定义一个管理器类,这个类继承models.Manger类。
  • 2)再在具体的模型类里定义一个自定义管理器类的对象。

自定义管理器类的应用场景

1)改变查询的结果集。
比如调用BookInfo.books.all()返回的是没有删除的图书的数据。
2)添加额外的方法。
管理器类中定义一个方法帮我们操作模型类对应的数据表。
使用self.model()就可以创建一个跟自定义管理器对应的模型类对象。

自定义管理器示例

自定义管理器代码

class BookInfoManager(models.Manager):
'''图书模型管理器类''' # 1.改变原有查询的结果集
def all(self):
# 1.调用父类的all方法,获取所有数据
books = super().all() # QuerySet
# 2.对books中的数据进行过滤
books = books.filter(isDelete=False)
# 返回books
return books # 2.封装方法,操作模型类对应的数据表(增删改查)
def create_book(self, btitle, bpub_date):
'''添加一本图书'''
# 1.创建一个图书对象
# 获取self所在的模型类
model_class = self.model
book = model_class()
# book = models.BookInfo()
book.btitle = btitle
book.bpub_date = bpub_date
# 2.添加进数据库
book.save()
# 3.返回book
return book # 一类
# booktest2_bookinfo
class BookInfo(models.Model):
'''图书模型类'''
# 图书名称
btitle = models.CharField(max_length=20, db_column='title')
# 图书名字唯一
# btitle = models.CharField(max_length=20, unique=True, db_index=True)
# 价格,最大位数为10,小数为2
# bprice = models.DecimalField(max_digits=10, decimal_places=2)
# 出版日期
bpub_date = models.DateField()
# bpub_date = models.DateField(auto_now_add=True) # 创建时间
# bpub_date = models.DateField(auto_now=True) # 更新时间
# 阅读量
bread = models.IntegerField(default=0)
# 评论量
bcomment = models.IntegerField(default=0)
# 删除标记
isDelete = models.BooleanField(default=False) # book = models.Manager() # 自定一个Manager类对象,管理器对象
objects = BookInfoManager() # 自定义一个BookInfoManager类的对象 # @classmethod
# def create_book(cls, btitle, bpub_date):
# '''添加一本图书'''
# # 创建一个cls类的对象
# obj = cls()
# obj.btitle = btitle
# obj.bpub_date = bpub_date
# # 添加进数据库
# obj.save()
# # 返回obj
# return obj

自定义管理器代码

自定义管理器的使用:
1.

BookInfo.objects.all() # objects是管理器中的objects,返回的是一个isDelete=0的值;

2.

from booktest.models import BookInfo
BookInfo.objects.create_book('test2', '1991-1-1')

其实在models.Manager里面已经封装了create方法,使用示例如下:
BookInfo.objects.create(btitlt='test3', bpub_date='1991-1-1')

应注意如果定义的图书模型类名换了比如class BookInfo,这个时候BookInfoManager中的book = BookInfo()也要改成
book = BookInfo1(),这样会很麻烦,但幸好,Manager里面有考虑到这一点,

# 获取self所在的模型类
model_class = self.model
book = model_class() # 上面两句相当于最后一句。
# book = BookInfo()

小结:

主旨:模型管理器类和模型类是通过在模型类中定义objects = BookInfoManager(),在模型管理器类中通过
model_class = self.model; book = model_class() 来建立关系的。

自定义模型管理器类方法获取默认收货地址

定义地址模型管理器类

class AddressManager(models.Manager):
"""地址管理器类"""
def get_default_address(self, user):
"""返回默认的地址"""
# self.model:获取self对象所在的模型类
try:
address = self.get(user=user, is_default=True)
except self.model.DoesNotExist:
# 不存在默认收货地址
address = None
return address

地址模型管理器类

地址模型类中引用地址模型管理器类的objects

class Address(BaseModel):
'''地址模型类'''
user = models.ForeignKey('User', verbose_name='所属账户')
receiver = models.CharField(max_length=20, verbose_name='收件人')
addr = models.CharField(max_length=256, verbose_name='收件地址')
zip_code = models.CharField(max_length=6, null=True, verbose_name='邮政编码')
phone = models.CharField(max_length=11, verbose_name='联系电话')
is_default = models.BooleanField(default=False, verbose_name='是否默认') # 自定义一个模型管理器对象
objects = AddressManager()

引用地址模型管理器类

在CBV中使用自定义模型管理器类中的方法

class AddressView(LoginRequiredMixin, View):
"""用户中心-订单页"""
def get(self, request):
"""返回用户中心信息页面"""
# 获取用户的默认收货地址
user = request.user
# try:
# address = Address.objects.get(user=user, is_default=True)
# except Address.DoesNotExist:
# address = None
# 使用自定义地址模型类管理器对象的获取默认收货地址方法
address = Address.objects.get_default_address(user)
# print("address:", address)
return render(request, "user_center_site.html", {"page": "address", "address": address})

CBV中使用自定义模型管理器类中的方法

模型-元选项

Django默认生成的表名:应用名小写_模型类名小写。

元选项:需要在模型类中定义一个元类Meta,在里面定义一个类属性db_table就可以指定表名。

如果改了应用名,而表名有不会自动更改,这个时候,就会出问题;
为了解决这个问题,我们要让模型类的表名不依赖于应用名;
使用 元选项,指定表名。

class BookInfo(models.Model):
'''图书模型类'''
btitle = models.CharField(max_length=20, db_column='title')
bpub_date = models.DateField()
bread = models.IntegerField(default=0)
bcomment = models.IntegerField(default=0)
isDelete = models.BooleanField(default=False) objects = BookInfoManager() # 自定义一个BookInfoManager类的对象
  
   # 使用元选项
class Meta:
db_table = 'bookinfo' # 指定模型类对应表名

Django之ORM-model模型关系的更多相关文章

  1. Django中ORM创建表关系

    一:django中ORM创建表关系 ORM创建外键关系 1.表与表之间的关系 1.表与表之间的关系 一对多 一对一 多对多 2.操作目标条件: 图书表 出版社表 作者表 作者详情表 3.外键关联 一对 ...

  2. python的Web框架,Django的ORM,模型基础,MySQL连接配置及增删改查

    Django中的ORM简介 ORM概念:对象关系映射(Object Relational Mapping,简称ORM): 用面向对象的方式描述数据库,去操作数据库,甚至可以达到不用编写SQL语句就能够 ...

  3. Python学习---django之ORM语法[对象关系映射]180124

    ORM语法[对象关系映射] ORM: 用面向对象的方式去操作数据库的创建表以及增删改查等操作. 优点:1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句.快速开发. 2 ...

  4. django中的Model模型一:

    在django的框架设计中采用了mtv模型,即Model,template,viewer Model相对于传统的三层或者mvc框架来说就相当对数据处理层,它主要负责与数据的交互,在使用django框架 ...

  5. Django之ORM多表关系创建

    ORM模型多表逻辑创建: 以图书和作者关系模型为例: models.py from django.db import models ''' 一本书只能被一个出版社出版; 一个出版社可以出版多本书; 一 ...

  6. Python-Django学习笔记(三)-Model模型的编写以及Oracle数据库的配置

    Django使用的 MTV 设计模式(Models.Templates.Views) 因此本节将围绕这三部分并按照这个顺序来创建第一个页面 模型层models.py 模型是数据唯一而且准确的信息来源. ...

  7. Django中的ORM如何通过数据库中的表格信息自动化生成Model 模型类?

    Inspectdb Django项目通过绑定的数据库中的相应表格直接自动化生成Model 模型类 python manage.py inspectdb Django 中的 ORM 可以实现对象关系映射 ...

  8. Django之ORM对象关系模型

    MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需 ...

  9. django Model模型二及Model模型对数据库的操作

    在django模型中负责与数据库交互的为Model层,Model层提供了一个基于orm的交互框架 一:创建一个最基本的Model from __future__ import unicode_lite ...

  10. 03.Django的MTV开发模式详解和模型关系构建

    ORM:对象关系映射 一:MTV开发模式把数据存取逻辑.业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的 Model-View-Controller(MVC)模式. 在这个模式中,Model 代 ...

随机推荐

  1. html+css-->background-img(背景图的设置)

    背景图:(相关验证代码请查看代码,在验证时需将当前不需要验证的代码注释掉)    1.inherit:从父元素继承属性设置    2.background-repeat:平铺(在图片大小小于元素尺寸时 ...

  2. C/C++中指向结构体变量的指针,调用指向的那个结构体中的成员

    设p是指向结构体变量的指针,则可以通过以下的方式,调用指向的那个结构体中的成员: (1)结构体变量.成员名.如,stu.num. (2)(*p).成员名.如,(*p).num. (3)p->成员 ...

  3. C#编程.函数.委托

    注:委托最重要的用途最讲到事件和事件处理时才能说清,这里先简单介绍一下关于委托的一些内容 委托是一种可以把引用存储为函数的类型.这听起来相当棘手,但其机制是非常简单的. 1)委托的声明非常类似与函数, ...

  4. 上车时机已到--.NETCore是适应时代发展的雄鹰利剑

    上车时机已到--.NETCore是适应时代发展的雄鹰利剑 要起飞了 .NET Core 3.0-prevew7:https://dotnet.microsoft.com/download/dotnet ...

  5. Java中返回值定义为int类型的 方法return 1返回的是int还是Integer&&finally中return问题

    在Java中返回值定义为int类型的 方法return 1:中返回的是Integer值,在返回的时候基本类型值1被封装为Integer类型. 定义一个Test类,在异常处理try中和finally中分 ...

  6. 神奇的 SQL 之 CASE表达式,妙用多多 !

    前言 历史考试选择题:黄花岗起义第一枪谁开的? A宋教仁 B孙中山 C黄兴 D徐锡麟,考生选C. 又看第二题:黄花岗起义第二枪谁开的? 考生傻了,就选了个B. 接着看第三题:黄花岗起义中,第三枪谁开的 ...

  7. 一份关于.NET Core云原生采用情况调查

    调查背景 Kubernetes 越来越多地在生产环境中使用,围绕 Kubernetes 的整个生态系统在不断演进,新的工具和解决方案也在持续发布.云原生计算的发展驱动着各个企业转向遵循云原生原则(启动 ...

  8. TIJ学习--RTTI(Runtime-Time Type Identification)

    TIJ学习--RTTI(Runtime-Time Type Identification) RTTI 运行时类型检查机制 获取一个类的Class引用的三种方法 class TestClass{} Te ...

  9. 深入学习 Intellij IDEA 调试技巧

    程序员的日常工作除了写代码之外,很大一部分时间将会在查找 BUG,解决问题.查找 BUG,离不开在 IDE 中调试代码.熟练的掌握调试技巧,可以帮助我们减少查找时间,快速定位问题. 在 IDEA 中调 ...

  10. 【iOS】iOS Error Domain=NSCocoaErrorDomain Code=3840 "未能完成操作。(“Cocoa”错误 3840。)"

    昨天遇到的这个问题,详细信息: ----->类和方法__25+[Manager noticeRequest:]_block_invoke399----->错误信息Error Domain= ...