zoukankan      html  css  js  c++  java
  • django基础之ORM基础知识

    创建表(模型): 

    表与表之间的关系:

    例如:做一个图书管理系统相关的模型

    1. 作者表:作者姓名,年龄,性别
    2. 作者详情表:生日,家庭住址,联系电话,生日。作者详情表和作者表需要绑定一对一的关系
    3. 出版社表:出版社有出版社名,地址,email
    4. 书籍表:书名,价格,出版日期书籍和作者是多对多的关系,因为一本书可以有多个作者,一个作者也可以写多本书和出版社是多对一的关系,一个出版社可以出版多本书,同一本书只能是一个出版社出版的

    创建表:

    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        age=models.IntegerField()
     
        # 与AuthorDetail建立一对一的关系
        authorDetail=models.OneToOneField(to="AuthorDetail")
     
    class AuthorDetail(models.Model):
     
        nid = models.AutoField(primary_key=True)
        birthday=models.DateField()
        telephone=models.BigIntegerField()
        addr=models.CharField( max_length=64)
        
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        city=models.CharField( max_length=32)
        email=models.EmailField()
     
     
    class Book(models.Model):
     
        nid = models.AutoField(primary_key=True)
        title = models.CharField( max_length=32)
        publishDate=models.DateField()
        price=models.DecimalField(max_digits=5,decimal_places=2)
        keepNum=models.IntegerField()<br>    commentNum=models.IntegerField()
     
        # 与Publish建立一对多的关系,外键字段建立在多的一方
        publish=models.ForeignKey(to="Publish",to_field="nid")
     
        # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
        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 

    添加表记录:

    普通字段的添加:

    方式一:
    publish_obj=mdoels.Publish(name="人民出版社",city="北京",email="renmin@163.com")
    publish_obj.save()    #将数据保存到数据库,相当于提交
    方式二:
    publish_obj=model.Publlish.objects.create(name="人民出版社",city="北京",email="renmin@163.com")
    方式三:
    models.Publish.objects.create(**request.POST.dict())

    外键字段的添加:

    方式一:
    Publish_obj=Publish.objects.get(nid=1)
    Book.objects.create(title="追风筝的人",publishDate="2012-12-12",price=665,pageNum=334,publlish=publish_obj)
    方式二:
    Book.objects.create(title="追风筝的人",publishDate="2012-12-12",price=665,pageNum=334,publlish_id=1)
    
    关键先搞清楚book_obj.publish是什么?

    多对多字段的添加:

    book_obj=models.Book.objects.create(title="追风筝的人",publishDate="2012-11-12",price=300,publish_id=1)
    author_kxl=models.Author.objects.create(name="kxl",age=18,authorDetail_id=1)
    author_yuan=models.Author.objects.create(name="yuan",age=23,authorDetail_id=2)
    
    book_obj.authors.add(author_kxl,author_yuan)#将某个特定的model对象添加到关联对象集合中   =========book_obj.authors.add(*[])
    book_obj.authors.create()#创建并保存一个新对象,然后将这个对象加入被关联对象的集合中然后返回这个新对象
    
    关键点在于:book_obj.authors是什么?
    它是所有与book_obj关联的author对象集合

    怎样解除关系:

    book_obj.authors.remove()     #将某个特定的对象从关联对象集合中去除

    book_obj.authors.remove(*[])

    book_obj.author.clear()      #清空被关联对象集合

    关联管理器:(class RelatedManager):

    "关联管理器"是在一对多或者多对多的关联上下文使用的管理器。它存在于下面两种情况:

    如:
    from django.db import models
    class Reporter(models.Model):
        #..........
        pass
    class Article(models.Model):
         reporter=models.Foreignkey(Reporter)
    
    这是一对多的例子:管理器reporter。article_set拥有下面方法
    如:
    class Topping(models.Model):
           #.........
            pass
    class Pizza(models.Model):
           toppings=models.ManytoManyField(Topping)
    
    这个例子是多对多:topping.pizza_set和pizza.toppings都拥有下面的方法。

    add(obj[,obj2,...])

    把指定的模型对象添加到关联对象集中。

    例如:
      b=Blog.objects.get(id=1)
      e=Entry.objects.get(id=234)

    create(**kwargs):

    remove(obj1[, obj2, ...]):

    clear():

    set()方法

    (搞得还不太清楚,后续更新........)

    查询表记录:

    单表查询相关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!!!QuerySet有update方法而object默认没有

     单表查询——基于双下划线

    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")     #获取name字段包含"ven"的
    
    models.Tb1.objects.filter(name__icontains="ven")    #icontains大小写不敏感
    
    models.Tb1.objects.filter(id__range=[1,3])          #id范围是1到3的,等价于SQL的between and
    
    类似的还有:startswith,istartswith,endswith,iendswith

    基于对象的跨表查询:

    一对多查询(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)

    一对多查询:(Author与AuthorDetail) 

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

    #查询kxl作者的手机号
        author_kxl=models.Author.objects.get(name="kxl")
        print(author_egon.authorDetail.telephone)

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

    #查询所有住址在北京的作者的姓名
    authorDetail_list=models.AuthorDetail.objects.filter(addr="北京")
    for obj in authorDetail_list:
          print(obj.author.name)
    
    #因为是一对一所以表名后面可以不要_set

    多对多查询:(Author与Book):

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

    #查询追风筝的人的所有作者的名字以及手机号
    book_obj=models.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):

    #查询kxl出过的所有书籍的名字
    author_obj=models.Author.objects.get(name="kxl")
    #限次那个数据库中找到名字为“kxl”的作者对象
    book_list=author_obj.book_set.all()
    #通过book_set找到与kxl作者相关的所有书籍
    for book_obj in book_list:
        print(book_obj.title)
    注意:如果在绑定关系时给字段添加了related_name的值可以代替"表名_set"

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

    Django提供了一种直观而高效的方式,查询中表示关联关系,可以自动确认SQLJOIN联系,查询将会变得比较方便

    关键点在于:正向查询按字段,反向查询按表名(还这句话!三遍了,足以证明非常重要)

    一对多:

    #查询人民出版社出版过的所有书籍的名字与价格:
    正向按字段(publish):
    queryResult=models.Book.objects.filter(publish__name="人民出版社")
                         .values_list("title","plrice") 反向按表名(book): queryResult=models.Publish.objects.filter(name="人民出版社")
              .values_list("book__title","book__price")

    多对多:

    #查询kxl出过的所有书籍的名字
    正向按字段(authors):
    queryResult=models.Book.objects.filter(author__name="kxl")
                          .values_list("title") 反向按表名(book): queryResult=models.Author.objects.filter(name="yuan")
           .values_list("book__title","book__price")

    练习:

    练习
    
    # 1. 查询人民出版社出版过的所有书籍的名字以及作者的姓名
    正向查询
        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")
    
    
    #2.手机号以151开头的作者出版过的所有书籍名称以及出版社名称
    
        queryResult=Book.objects
                .filter(authors__authorDetail__telephone__regex="151")
                .values_list("title","publish__name")

    持续更新....

  • 相关阅读:
    数据库三大范式另一角度的理解
    Log4j和Slf4j的联系和区别
    cglib和Jdk的对比
    Git- 忽略文件 ignore 无效
    GIT报错:git did not exit cleanly (exit code 1)
    Nginx和Zuul配合使用后,Cookie写入问题
    RabbitMQ报错:undefined: There is no template at js/tmpl/login.ejs
    Feign报错:The bean 'xxxxx.FeignClientSpecification' could not be registered.
    ES报错:NoNodeAvailableException[None of the configured nodes are available
    SpringBoot报错:
  • 原文地址:https://www.cnblogs.com/kxllong/p/8361326.html
Copyright © 2011-2022 走看看