zoukankan      html  css  js  c++  java
  • Django模型(ORM)

    1、ORM与数据库的映射关系:

                  ORM                  数据库

                   类名----------------表名

                  属性----------------字段

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

    2、连接mysql数据库:

           在项目的 settings.py 文件中找到 DATABASES 配置项,将其信息修改为: 

     1 DATABASES = {
     2     'default': {
     3         'ENGINE': 'django.db.backends.mysql',  # 或者使用 mysql.connector.django
     4         'NAME': 'test',                        #数据库名称
     5         'USER': 'test',                        #用户
     6         'PASSWORD': 'test123',                 #密码
     7         'HOST':'localhost',                    #数据库的连接地址
     8         'PORT':'3306',                         #数据库启用端口
     9     }
    10 }

    3、创建表(建立模型)      

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

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

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

    注意事项:

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

    2>id 字段是自动添加的

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

    4>这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。

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

    6>外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

    3.1、字段选项:

             每个字段有一些特有的参数,例如,CharField需要max_length参数来指定VARCHAR数据库字段的大小。还有一些适用于所有字段的通用参数。 这些参数在文档中有详细定义,这里我们只简单介绍一些最常用的:

             

    (1)null
    
    如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
    
    (2)blank
    如果为True,该字段允许不填。默认为False。
    要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
    如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
    
    (3)default
    字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。
    
    (4)primary_key
    如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
    Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
    否则没必要设置任何一个字段的primary_key=True。
    
    (5)unique
    如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
    
    (6)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'

    4、添加表字段:

    4.1、添加普通字段:

    4.1.1、方式一:

    1 publish_obj=Publish(name="人民出版社",city="北京",email="renMin@163.com")
    2 publish_obj.save()  # 将数据保存到数据库

    4.1.2、方式二、

    1 返回值publish_obj是添加的记录对象
    2 publish_obj=Publish.objects.create(name="人民出版社",city="北京",email="renMin@163.com")

    4.2、添加外键字段(一对多):

    4.2.1、方式一:

    1  publish_obj=Publish.objects.get(nid=1)
    2  Book.objects.create(title="语文",publishDate="2012-12-12",price=665,pageNum=334,publish=publish_obj)   #首先获取外键id字段,然后添加相应的字段

    4.2.2、方式二:

    Book.objects.create(title="语文",publishDate="2012-12-12",price=665,pageNum=334,publish_id=1)   #直接添加外键的ID字段
    

    4.3、添加外键字段(多对多)

    1 book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-11-12",price=69,pageNum=314,publish_id=1)
    2  
    3 author_yuan=Author.objects.create(name="yuan",age=23,authorDetail_id=1)
    4 author_egon=Author.objects.create(name="egon",age=32,authorDetail_id=2)
    5  
    6 book_obj.authors.add(author_egon,author_yuan)    #  将某个特定的 model 对象添加到被关联对象集合中。   ======= book_obj.authors.add(*[])
    7  
    8 book_obj.authors.create()      #创建并保存一个新对象,然后将这个对象加被关联对象的集合中,然后返回这个新对象。
    9 #解除绑定关系
    10 book_obj.authors.remove()     # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])
    11 book_obj.authors.clear()       #清空被关联对象集合。
      

    5、查询表记录:

    5.1、查询相关的API:

     1 <1> all():                 查询所有结果
     2  
     3 <2> filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
     4  
     5 <3> get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
     6                            如果符合筛选条件的对象超过一个或者没有都会抛出错误。
     7  
     8 <5> exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象
     9  
    10 <4> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
    11                            model的实例化对象,而是一个可迭代的字典序列
    12  
    13 <9> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
    14  
    15 <6> order_by(*field):      对查询结果排序
    16  
    17 <7> reverse():             对查询结果反向排序
    18  
    19 <8> distinct():            从返回结果中剔除重复纪录
    20  
    21 <10> count():              返回数据库中匹配查询(QuerySet)的对象数量。
    22  
    23 <11> first():              返回第一条记录
    24  
    25 <12> last():               返回最后一条记录
    26  
    27 <13> exists():             如果QuerySet包含数据,就返回True,否则返回False
    28
    29 注意区分object与querySet的区别 !!!

    5.2、双下划线之单表查询:

     1 models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
     2  
     3 models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
     4 models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
     5  
     6 models.Tb1.objects.filter(name__contains="ven")
     7 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
     8  
     9 models.Tb1.objects.filter(id__range=[1, 2])      # 范围bettwen and
    10  
    11 startswith,istartswith, endswith, iendswith

    5.3、基于对象的跨表查询

    5.3.1、一对多查询:

    正向查询(按一对多中的多的字段查询):

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

    反向查询(按一对多中的一的表名查询):

    1 # 查询 人民出版社出版过的所有书籍
    2  
    3     publish=Publish.objects.get(name="人民出版社")
    4  
    5     book_list=publish.book_set.all()  # 与人民出版社关联的所有书籍对象集合
    6  
    7     for book_obj in book_list:
    8         print(book_obj.title)

    5.3.2、多对多查询: 

    正向查询(按字段): 

    1 # 语文所有作者的名字以及手机号
    2  
    3     book_obj=Book.objects.filter(title="语文").first()
    4  
    5     authors=book_obj.authors.all()
    6  
    7     for author_obj in authors:
    8  
    9         print(author_obj.name,author_obj.authorDetail.telephone)

    反向查询(按表名):

    1 # 查询egon出过的所有书籍的名字
    2  
    3     author_obj=Author.objects.get(name="egon")
    4     book_list=author_obj.book_set.all() #与egon作者相关的所有书籍
    5  
    6     for book_obj in book_list:
    7         print(book_obj.title)

     5.3.3、一对一查询:

    正向查询(按字段):

    1 # 查询egon作者的手机号
    2  
    3     author_egon=Author.objects.get(name="egon")
    4     print(author_egon.authorDetail.telephone)

    反向查询(按表名):

    1 # 查询所有住址在北京的作者的姓名
    2  
    3     authorDetail_list=AuthorDetail.objects.filter(addr="beijing")
    4  
    5     for obj in authorDetail_list:
    6         print(obj.author.name)

    注意:如果在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值覆写 FOO_set 的名称,那么反向查询时按照related_name来查。

    5.4、基于双下划线的跨表查询:

    Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止。

     1 # 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)
     2 
     3     # 正向查询 按字段:publish
     4 
     5     queryResult=Book.objects
     6             .filter(publish__name="人民出版社")
     7             .values_list("title","price")
     8 
     9     # 反向查询 按表名:book
    10 
    11     queryResult=Publish.objects
    12               .filter(name="人民出版社")
    13               .values_list("book__title","book__price")
    14 
    15 
    16 
    17 # 练习2: 查询egon出过的所有书籍的名字(多对多)
    18 
    19     # 正向查询 按字段:authors:
    20     queryResult=Book.objects
    21             .filter(authors__name="yuan")
    22             .values_list("title")
    23 
    24     # 反向查询 按表名:book
    25     queryResult=Author.objects
    26               .filter(name="yuan")
    27               .values_list("book__title","book__price")
    28 
    29 
    30 # 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名
    31 
    32 
    33     # 正向查询
    34     queryResult=Book.objects
    35             .filter(publish__name="人民出版社")
    36             .values_list("title","authors__name")
    37     # 反向查询
    38     queryResult=Publish.objects
    39               .filter(name="人民出版社")
    40               .values_list("book__title","book__authors__age","book__authors__name")
    41 
    42 
    43 # 练习4: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称
    44 
    45     queryResult=Book.objects
    46             .filter(authors__authorDetail__telephone__regex="151")
    47             .values_list("title","publish__name")

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

    6、聚合查询与分组查询

    6.1、聚合查询:aggregate(*args, **kwargs)

  • 相关阅读:
    CSS3新增文本属性实现图片点击切换效果
    swipe和swiper的区别
    uncaught syntaxerror: unexpected token
    科协前辈的阿里面试经验转载1
    Oracle 分析函数
    Jakarta Commons HttpClient 学习笔记 (二)
    Ubuntu eclipse下android virtual device manager不能删除AVD
    Android的界面设计工具——DroidDraw
    JS异步请求数据
    Ubuntu配置JDK和Android环境变量
  • 原文地址:https://www.cnblogs.com/brightbrother/p/7875292.html
Copyright © 2011-2022 走看看