Django值ORM

ORM(object relational mapping): 对象关系映射

映射关系:

     表名  <-------> 类名

       字段  <-------> 属性

    表记录 <------->类实例对象

建立模型(model)

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名和年龄。

作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)

出版商模型:出版商有名称,所在城市以及email。

书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。

 1 class Author(models.Model):
 2     nid = models.AutoField(primary_key=True)
 3     name=models.CharField( max_length=32)
 4     age=models.IntegerField()
 5
 6     # 与AuthorDetail建立一对一的关系
 7     authorDetail=models.OneToOneField(to="AuthorDetail")
 8
 9 class AuthorDetail(models.Model):
10
11     nid = models.AutoField(primary_key=True)
12     birthday=models.DateField()
13     telephone=models.BigIntegerField()
14     addr=models.CharField( max_length=64)
15
16 class Publish(models.Model):
17     nid = models.AutoField(primary_key=True)
18     name=models.CharField( max_length=32)
19     city=models.CharField( max_length=32)
20     email=models.EmailField()
21
22
23 class Book(models.Model):
24
25     nid = models.AutoField(primary_key=True)
26     title = models.CharField( max_length=32)
27     publishDate=models.DateField()
28     price=models.DecimalField(max_digits=5,decimal_places=2)
29     keepNum=models.IntegerField()<br>    commentNum=models.IntegerField()
30
31     # 与Publish建立一对多的关系,外键字段建立在多的一方
32     publish=models.ForeignKey(to="Publish",to_field="nid")
33
34     # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
35     authors=models.ManyToManyField(to=‘Author‘)  

通过设置项目目录中settings.py文件中LOGGING参数可查看每一次数据库操作对应的sql语句

LOGGING = {
    ‘version‘: 1,
    ‘disable_existing_loggers‘: False,
    ‘handlers‘: {
        ‘console‘:{
            ‘level‘:‘DEBUG‘,
            ‘class‘:‘logging.StreamHandler‘,
        },
    },
    ‘loggers‘: {
        ‘django.db.backends‘: {
            ‘handlers‘: [‘console‘],
            ‘propagate‘: True,
            ‘level‘:‘DEBUG‘,
        },
    }
} 

注意事项:

1、 表的名称APPName_ModelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称  

2、id 字段是自动添加的

3、对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名

4、定义好模型之后,你需要告诉Django 使用这些模型。你要做的就是修改配置文件中的INSTALL_APPS中设置,在其中添加models.py所在应用的名称。

5、外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None,blank=True用于Admin操作时允许输入框为空(如下)

字段选项

(1)null

如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.

(1)blank

如果为True,该字段允许不填。默认为False。
要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。

(2)default

字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。

(3)primary_key

如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
否则没必要设置任何一个字段的primary_key=True。

(4)unique

如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的

(5)choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。

这是一个关于 choices 列表的例子:

YEAR_IN_SCHOOL_CHOICES = (
    (‘FR‘, ‘Freshman‘),
    (‘SO‘, ‘Sophomore‘),
    (‘JR‘, ‘Junior‘),
    (‘SR‘, ‘Senior‘),
    (‘GR‘, ‘Graduate‘),
)
每个元组中的第一个元素,是存储在数据库中的值;第二个元素是在管理界面或 ModelChoiceField 中用作显示的内容。 在一个给定的 model 类的实例中,想得到某个 choices 字段的显示值,就调用 get_FOO_display 方法(这里的 FOO 就是 choices 字段的名称 )。例如:

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        (‘S‘, ‘Small‘),
        (‘M‘, ‘Medium‘),
        (‘L‘, ‘Large‘),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)

>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
‘L‘
>>> p.get_shirt_size_display()
‘Large‘  

添加表记录

1.普通字段

方式1
publish_obj=Publish(name="人民出版社",city="北京",email="[email protected]")
publish_obj.save() # 将数据保存到数据库

方式2 <br>返回值publish_obj是添加的记录对象
publish_obj=Publish.objects.create(name="人民出版社",city="北京",email="[email protected]")

2. 外键字段

方式1:
   publish_obj=Publish.objects.get(nid=1)
   Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish=publish_obj)

方式2:
   Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish_id=1)  

3. 多对多字段

book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-11-12",price=69,pageNum=314,publish_id=1)

author_yuan=Author.objects.create(name="yuan",age=23,authorDetail_id=1)
author_egon=Author.objects.create(name="egon",age=32,authorDetail_id=2)

book_obj.authors.add(author_egon,author_yuan)    #  将某个特定的 model 对象添加到被关联对象集合中。   =======    book_obj.authors.add(*[])

book_obj.authors.create()      #创建并保存一个新对象,然后将这个对象加被关联对象的集合中,然后返回这个新对象。

查询表记录

查询相关API

<1> all():                 查询所有结果
<2> filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

<3> get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
                           如果符合筛选条件的对象超过一个或者没有都会抛出错误。

<4> exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象

<5> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                           model的实例化对象,而是一个可迭代的字典序列

<6> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

<7> order_by(*field):      对查询结果排序

<8> reverse():             对查询结果反向排序

<9> distinct():            从返回结果中剔除重复纪录

<10> count():              返回数据库中匹配查询(QuerySet)的对象数量。

<11> first():              返回第一条记录

<12> last():               返回最后一条记录

<13> exists():             如果QuerySet包含数据,就返回True,否则返回False

注意区分object与querySet的区别

双下划线之单表查询

类型 描述
exact 精确匹配: polls.get_object(id__exact=14).
iexact 忽略大小写的精确匹配: polls.objects.filter(slug__iexact="foo") 匹配 fooFOOfOo, 等等.
contains
大小写敏感的内容包含测试: polls.objects.filter(question__contains="spam")

返回question 中包含 "spam" 的所有民意测验.

(仅PostgreSQL 和 MySQL支持. SQLite 的LIKE 语句不支持大小写敏感特性.

对Sqlite 来说, contains 等于 icontains.)

icontains 大小写不敏感的内容包含测试:
gt 大于: polls.objects.filter(id__gt=4).
gte 大于等于.
lt 小于.
lte 小于等于.
ne 不等于.
in 位于给定列表中: polls.objects.filter(id__in=[1, 3, 4]) 返回一个 polls 列表(ID 值分别是 1或3或4).
startswith
大小写敏感的 starts-with: polls.objects.filter(question__startswith="Would").(仅PostgreSQL 和MySQL支持.

SQLite 的LIKE 语句不支持大小写敏感特性.

对Sqlite 来说,``startswith`` 等于 istartswith)

endswith 大小写敏感的 ends-with. (仅PostgreSQL 和 MySQL)
istartswith 大小写不敏感的 starts-with.
iendswith 大小写不敏感的 ends-with.
range
范围测试: polls.objects.filter(pub_date__range=(start_date, end_date))

返回 pub_date 位于 start_date 和 end_date (包括)之间的所有民意测验

year 对 date/datetime 字段, 进行精确的  匹配: polls.get_count(pub_date__year=2005).
month 对 date/datetime 字段, 进行精确的  匹配:
day 对 date/datetime 字段, 进行精确的  匹配:
isnull True/False; 做 IF NULL/IF NOT NULL 查询: polls.objects.filter(expire_date__isnull=True).
models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值

models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感

models.Tb1.objects.filter(id__range=[1, 2])      # 范围bettwen and

startswith,istartswith, endswith, iendswith 

基于对象的跨表查询

1. 一对多查询(如Publish和Book)

正向查询(按字段:publish):

# 查询nid=1的书籍的出版社所在的城市
book_obj=Book.objects.get(nid=1)
print(book_obj.publish.city) # book_obj.publish 是nid=1的书籍对象关联的出版社对象  

反向查询(按表名:book_set):

# 查询 人民出版社出版过的所有书籍

publish=Publish.objects.get(name="人民出版社")

book_list=publish.book_set.all()  # 与人民出版社关联的所有书籍对象集合

for book_obj in book_list:
     print(book_obj.title)

2. 一对一查询(如Author和AuthorDetail)

正向查询(按字段:authorDetail):

# 查询egon作者的手机号

author_egon=Author.objects.get(name="egon")
print(author_egon.authorDetail.telephone)

反向查询(按表名:author):

# 查询所有住址在北京的作者的姓名

authorDetail_list=AuthorDetail.objects.filter(addr="beijing")

for obj in authorDetail_list:
     print(obj.author.name)

3. 多对多查询(如Author和Book)

正向查询(按字段:authors):

# 金瓶眉所有作者的名字以及手机号

book_obj=Book.objects.filter(title="金瓶眉").first()

authors=book_obj.authors.all()

for author_obj in authors:

     print(author_obj.name,author_obj.authorDetail.telephone)

反向查询(按表名:book_set):

# 查询egon出过的所有书籍的名字

 author_obj=Author.objects.get(name="egon")
 book_list=author_obj.book_set.all() #与egon作者相关的所有书籍

 for book_obj in book_list:
      print(book_obj.title)

注意:

可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Book model 中做一下更改: publish = ForeignKey(Blog, related_name=‘bookList‘),那么接下来就会如我们看到这般:

# 查询 人民出版社出版过的所有书籍

publish=Publish.objects.get(name="人民出版社")

book_list=publish.bookList.all()  # 与人民出版社关联的所有书籍对象集合

基于双下划线的跨表查询

# 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)

    # 正向查询 按字段:publish

queryResult=Book.objects.filter(publish__name="人民出版社")
            .values_list("title","price")

    # 反向查询 按表名:book

queryResult=Publish.objects.filter(name="人民出版社")
              .values_list("book__title","book__price")

# 练习2: 查询egon出过的所有书籍的名字(多对多)

    # 正向查询 按字段:authors:
queryResult=Book.objects.filter(authors__name="yuan")
            .values_list("title")

    # 反向查询 按表名:book
queryResult=Author.objects.filter(name="yuan")
              .values_list("book__title","book__price")

# 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名

    # 正向查询
queryResult=Book.objects.filter(publish__name="人民出版社")
            .values_list("title","authors__name")
    # 反向查询
queryResult=Publish.objects.filter(name="人民出版社")
              .values_list("book__title","book__authors__age","book__authors__name")

# 练习4: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称

queryResult=Book.objects.filter(authors__authorDetail__telephone__regex="151")
            .values_list("title","publish__name")

注意:

反向查询时,如果定义了related_name ,则用related_name替换表名,例如: publish = ForeignKey(Blog, related_name=‘bookList‘):

# 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)

    # 反向查询 不再按表名:book,而是related_name:bookList

queryResult=Publish.objects.filter(name="人民出版社").values_list("bookList__title","bookList__price")
时间: 2024-11-01 09:20:45

Django值ORM的相关文章

[Django]Django的orm中get和filter的不同

Django的orm中get和filter的不同 Django的orm框架对于业务复杂度不是很高的应用来说还是不错的,写起来很方面,用起来也简单.对于新手来说查询操作中最长用的两个方法get和filter有时候一不注意就会犯下一些小错误.那么今天就来小节下这两个方法使用上的不同. 我常用的是1.5版本的django,就以此为例来说说吧. 文档 首先对比下两个函数文档上的解释. get Returns the object matching the given lookup parameters,

人生苦短,我用python-- Day19 django框架之URL路由系统、视图应用、模板应用、django之orm应用

目录 一.django的URL应用 二.django的视图应用 三.django的模板应用 四.django的orm应用 补充: 补充一:getlis 应用场景:当前端发送的数据为多个的时候,后台如果还用get获取数据,那么就会出问题,所以这里有一个getlist方法进行数据的获取. 试验案例:当前端有一个多选的checkbox的时候,那么就要使用getlist进行获取数据了 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^get

Django 数据库ORM 操作 - 字段的类型和参数

通过Django的ORM创建表的时候,我们需要定义自己的类. 定义类的时候,他有各种各样的字段类型,每个字段都有自己的参数可以进行配置,下面简单的归纳一下. 首先看看字段的类型.尽管Python提供了近乎20种类型,他转换成数据库表之后,其实本质就是4个类型:字符串,数字,时间和二进制. AutoField(Field)     - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField)     - bigint自增列,必须填入参数 prim

Django中ORM介绍和字段及其参数

ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中. ORM在业务逻辑层和数据库层之间充当了桥梁的作用. ORM的由来 字母‘O’起源于“对象”(Object),'R'代表“关系”(Relational). 几乎所有的软件开发过程中都会涉及到对象和关系数据库.在用户层面和业务逻辑层

59 Django基础三件套 , 模板{{}}语言 , 程序连mysql Django项目app Django中ORM的使用

主要内容: 1 form表单中提交数据的三要素 form标签必须要有action和method的属性 所有获取用户输入的标签必须放在form表单里,也必须要有那么name属性.因为往后端提交数据的时候name所对应的是关键字, input输入的值为value.在后端显示为字典的模式, 如果不写name关键字,则取不到值. 必须要有submit按钮. 2 Django 基础三件套 from Django.shortcuts import HttpResponse, render, redirect

Django中ORM字段以及字段参数介绍

一:Django中ORM的介绍 1.ORM的概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中. ORM在业务逻辑层和数据库层之间充当了桥梁的作用. 2.ORM的来源 让我们从O/R开始.字母O起源于"对象"(Object),而R则来自于"关系"(Relational)

Django的orm中get和filter的不同

Django的orm框架对于业务复杂度不是很高的应用来说还是不错的,写起来很方面,用起来也简单.对于新手来说查询操作中最长用的两个方法get和filter有时候一不注意就会犯下一些小错误.那么今天就来小节下这两个方法使用上的不同. 首先对比下两个函数文档上的解释. get Returns the object matching the given lookup parameters, which should be in the format described in Field lookups

Django 之 orm操作

静态文件配置 所有的html文件默认都写在templates文件夹下 所有的静态文件(css,js,前端第三方类库)默认都放在static文件夹下 html页面引入外部资源的方式:cdn.本地 静态文件配置 STATIC_URL: 和静态文件夹的名字没有关系 默认情况下这个前缀跟静态文件夹名字一样!!! html文件head导入的本地数据,一次前缀开头,否则无法实现相应的效果 STATICFILES_DIRS: 暴露给外界能够访问服务器静态文件夹下面所有的资源 会依次查找列表中所有的静态文件路径

django -- 实现ORM登录

前戏 上篇文章写了一个简单的登录页面,那我们可不可以实现一个简单的登录功能呢?如果登录成功,给返回一个页面,失败给出错误的提示呢? 在之前学HTML的时候,我们知道,网页在往服务器提交数据的时候,都是在form表单里,并且要满足下面的几个条件: 1.form标签必须要有action和method属性 2.所有获取用户的标签必须放在form表单中,必须要有name属性 3.必须要有submit按钮 Django必学三件套 Django 基础必会三件套,render,HttpResponse,red