zoukankan      html  css  js  c++  java
  • Django---model基础(单表)

    ORM

    一、映射关系:

              表名<--------------->类名
              字段<-------------->属性
              表记录<----------->类实例对象

    创建表(建立表模型)

    二、单表

    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        authors = models.CharField(max_length=32)
        publishDate = models.DateField()
        price = models.DecimalField(max_digits=5, decimal_places=2)

    1.通过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、models.AutoField  自增列= int(11)
        如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
     2、models.CharField  字符串字段
        必须 max_length 参数
     3、models.BooleanField  布尔类型=tinyint(1)
        不能为空,Blank=True
     4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
        继承CharField,所以必须 max_lenght 参数
     5、models.DateField  日期类型 date
       对于参数,auto_now =True则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
     6、models.DateTimeField  日期类型 datetime
       同DateField的参数
     7、models.Decimal  十进制小数类型= decimal
       必须指定整数位max_digits和小数位decimal_places
     8、models.EmailField  字符串类型(正则表达式邮箱)=varchar
       对字符串进行正则表达式
     9、models.FloatField  浮点类型= double
    10、models.IntegerField  整形 11、models.BigIntegerField  长整形   integer_field_ranges ={     'SmallIntegerField':(-32768,32767),      'IntegerField':(-2147483648,2147483647),     'BigIntegerField':(-9223372036854775808,9223372036854775807),     'PositiveSmallIntegerField':(0,32767),     'PositiveIntegerField':(0,2147483647),   } 12、models.IPAddressField  字符串类型(ip4正则表达式) 13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)   参数protocol可以是:both、ipv4、ipv6   验证时,会根据设置报错 14、models.NullBooleanField  允许为空的布尔类型 15、models.PositiveIntegerFiel  正Integer 16、models.PositiveSmallIntegerField  正smallInteger 17、models.SlugField  减号、下划线、字母、数字 18、models.SmallIntegerField  数字   数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField  字符串=longtext 20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField  字符串,地址正则表达式 22、models.BinaryField  二进制 23、models.ImageField图片 24、models.FilePathField文件

    添加表记录

    三、

    1.添加表记录(save和create)

    方式一:book_obj=models.Book(title=title)
                  book_obj.save() #将数据保存到数据库

    方式二:book_obj=models.Book.objects.create(title=title)

    2.查询

    1.all       查询所有结果            用法:models.表名.objects.all()      结果是QuerySet集合    [model对象]
    2.filter             查询所给筛选匹配的对象       用法:models.表名.objects.filter()                 结果是:QuerySet集合     如:ret=models.表名.objects.filter(auther='mqj',price=123)
    3.get                查询所给筛选匹配的对象,返回值只有一个,如果筛选的对象超过一个或没有就会报错      用法:models.表名.objects.get()    结果是:model对象         如:ret=models.表名.objects.get(auther="yuan")
    4.exclude        包含筛选条件你匹配的对象  用法:ret=models.表名.objects.exclude
    (author="yuan")
    5.values 方法  返回的是列表中一个一个的可迭代字典  返回的是列表中一个一个的可迭代字典      用法:ret=models.表名.objects.filter(author="yuan").value("title","price")
    6.values_list 方法   返回的是列表中一个一个的元组序列         用法:ret=models.表名.objects.filter(author="yuan").value_list("title","price")
    7.reverse():对查询的结果反向排序
    8.order_by():对查询的结果排序
    9.ddistinct(): 返回的结果中剔除重复记录
    10.count():    返回数据库匹配查询数量               用法:ret=models.Book.objects.filter(author="yuan").count()
    11.first():      返回第一条记录                             用法:ret = models.Book.objects.all().first()
    12.last():       返回最后一条记录                          用法:ret = models.Book.objects.all().last()
    13.exists():    返回True或False                          用法:ret=models.Book.objects.all().existst()

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

    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.filter(name__contains="ven")
    
    models.Tb1.objects.filter(name__icontains="ven")
    
    models.Tb1.obiects.filter(id__range=[1,2])   #范围bettwen and
    
    
    startswith,istartswith,endswith,iendswith

    4.修改

    修改方式1:save(效率低)
    如:   book_obj=models.Book.objects.filter(nid=id)[0]
                 book_obj.title="金平"
                book_obj.save()
    修改方式2:
            title=request.POST.get("title")
            authors=request.POST.get("authors")
            pubDate=request.POST.get("pubDate")
            price=request.POST.get("price")
            models.Book.objects.filter(nid=id).update(title=title,authors=authors,publishDate=pubDate,price=price)
    
    

    5.删除:

         delect

    了不起的双下划线:
                    models.表名.objects.filter(id__gt=10)
                    models.表名.objects.filter(title__startswith="py")
                    models.Tb1.objects.filter(id__range=[1, 2]) 
                    models.Tb1.objects.filter(id__in=[11, 22, 33])

     四、表关联操作

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

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

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

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

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

    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)
        publish = models.ForeignKey("Publish", related_name="bookList")
        authorlist = models.ManyToManyField("Author", related_name="bookList")
        def __str__(self):
            return self.title
    class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) def __str__(self): return self.name
    class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() def __str__(self): return self.name
    class AuthorDetail(models.Model): tel=models.IntegerField() addr=models.CharField(max_length=32) author=models.OneToOneField("Author",related_name="authorList")

     表关系:

          1.一对多

          2.一对一

          3.多对多

    添加记录:
       一对多:
         创建一对多:
                    publish=models.ForeignKey("Publish",related_name="bookList")
             添加记录方式1:
                                   models.Book.objects.create(publish_id=1)
             添加记录方式2:
                                  pubObj=models.Publish.objects.filter(name="人民出版社")[0]
                                  models.Book.objects.create(publish=pubObj)  # 关联的出版社对象
    
     多对多:
             创建多对多关系:
                   authorlist=models.ManyToManyField("Author",related_name="bookList")
             多对多添加记录:
                   book_obj=models.Book.objects.create(title="追风筝的人", price=100, publishDate="2017-12-12", publish_id=2)
                   alex_obj=models.Author.objects.filter(name="alex")[0]
                   egon_obj=models.Author.objects.filter(name="egon")[0]
                     
                    book_obj.authorlist.add(alex_obj,egon_obj)
    查询记录:
             正向查询:
             一对多:
                   linux_obj=models.Book.objects.filter(title="linux").first()
                   print(linux_obj.publish.name)  # 与这本书对象关联的出版社对象的名字
             多对多:
                   linux_obj=models.Book.objects.filter(title="linux").first()
                   print(linux_obj.authorlist.all()) # 与这本书关联的所有作者对象集合
             反向查询:
              #一对多的反向查询:
                        eg:人民出版社出版过的书籍的名字
                        publish_obj=models.Publish.objects.filter(name="人民出版社")[0]
                        print(publish_obj.bookList.all()) # 与该年出版社关联的所有书籍对象的集合 
                        #多对多的反向查询:
                        查询yuan出版过的所有书籍的名字和价格:
                        author_yuan=models.Author.objects.get(name="yuan")
                        print(author_yuan.bookList.all())  # 与该作者关联的所有书籍书籍对象的集合

     2.基于对象的查询

    基于对象关联查询:    
        
        if 一对多查询(Book--Publish):
              正向查询,按字段:
              book_obj.publish   :  与这本书关联的出版社对象    book_obj.publish.addr: 与这本书关联的出版社的地址
              反向查询,按表名_set
              publish_obj.book_set: 与这个出版社关联的书籍对象集合    publish_obj.book_set.all() :[obj1,obj2,....]    
        
        if 一对一查询(Author---AuthorDetail):
              正向查询,按字段:
              author_obj.ad : 与这个作者关联的作者详细信息对象
              
              反向查询:按表名:
              author_detail_obj.author  : 与这个作者详细对象关联的作者对象
              
        if  多对多(Book----Author):
    
            正向查询,按字段:  
            
            book_obj.authorList.all(): 与这本书关联的所有这作者对象的集合  [obj1,obj2,....]
            
            反向查询,按表名_set:
            author_obj.book_set.all() : 与这个作者关联的所有书籍对象的集合

    3.双下划线的跨表查询 

    查询python这本书出版社的地址
        # 方式一:
        # book_obj=models.Book.objects.filter(title="python").first()
        # print(book_obj.publish.name)
    
        # 方式二(双下划线):
        # book_obj=models.Book.objects.filter(title="python").values("publish__addr")
        # print(book_obj)
    
        # 方式三(双下划线):
        # book_obj=models.Publish.objects.filter(bookList__title="python").values("addr")
        # print(book_obj)
        
     查询老男孩出版社出版过的所有书籍的名字与价格
        # 方式一:
        # book_obj=models.Publish.objects.filter(name="老男孩出版社").first()
        # print(book_obj.bookList.all().values("title","price"))
    
    
        # 方式二:(双下划线)
        # book_obj=models.Publish.objects.filter(name="老男孩出版社").values("bookList__title","bookList__price")
        # print(book_obj)
    
        # 方式三(双下划线):
        # book_obj=models.Book.objects.filter(publish__name="老男孩出版社").values("title","price")
        # print(book_obj)
    
        # egon出版过的所有书籍名称以及出版社名称
        # book_obj=models.Author.objects.filter(name="egon").values("bookList__title","bookList__authorlist__name")
        # print("book_obj",book_obj)
    
    查询egon出过的所有书籍的名字(多对多)
        book_obj=models.Author.objects.filter(name="egon").values("bookList__title")
        print(book_obj)
    
        book_obj=models.Book.objects.filter(authorlist__name="egon").values("title")
        print(book_obj)
    
    手机号以151开头的作者出版过的所有书籍名称以及出版社名称
    
        # book_obj=models.AuthorDetail.objects.filter(tel__startswith="151").first()
        # print(book_obj.author.bookList.all().values("title","publish__name"))
    
        # 方法2
        # models.Book.objects.filter(authorlist__author_detail__tel__startswith="151").values("title", "publish__name")
    if 一对多查询(Book--Publish):
            正向查询,按字段:        
            # 查询linux这本书的出版社的名字:
            models.Book.objects.all().filter(title="linux").values("publish__name")
            反向查询:按表名:
            # 查询人民出版社出版过的所有书籍的名字
            models.Publish.objects.filter(name="人民出版社出版").values("book__title")
            
        if 一对一查询(Author---AuthorDetail):
             正向查询,按字段:
            models.Author.objects.filter(name="egon).values("ad__tel")
            反向查询:按表名:
            models.AuthorDetail.objects.filter(tel="151").values("author__name")
            
        if  多对多(Book----Author):
            正向查询,按字段:
            models.Book.objects.filter(title="python").values("authorList__name")     [{},{},{},{}]
            
            正向查询,按表名:
            models.Author.objects.filter(name="alex").values("book__price")
        
    
    注意:
    
     publish=models.ForeignKey("Publish",related_name="bookList")
     authorlist=models.ManyToManyField("Author",related_name="bookList") 
     ad=models.models.OneToOneField("AuthorDetail",related_name="authorInfo")
     
     反向查询的时候都用:related_name

     4.查询

    一对多的查询
        # 查询linux这本书的出版社的地址?
    
        #linux_obj=models.Book.objects.filter(title="linux").first()
        #
        # print(linux_obj.title)
        # print(linux_obj.price)
        # print(linux_obj.publishDate)
        #
        # print(linux_obj.publish.name)  # 与这本书对象关联的出版社对象
        #print(linux_obj.publish.addr)  # 与这本书对象关联的出版社对象
    
        # 人民出版社出版过的书籍的名字
        # publish_obj=models.Publish.objects.filter(name="人民出版社")[0]
        # print(publish_obj.bookList.all())  # 与这个出版社对象关联的所有书籍对象
    
    
    多对多的查询
    
        # 查询追风筝的人的所有作者的姓名和年龄
    
        # book_obj=models.Book.objects.filter(title="追风筝的人")[0]
        # print("=====",book_obj.authorlist.all()  )         #  与这本书关联的所有作者对象,集合对象
        # authorlist=book_obj.authorlist.all()
        # print(authorlist.values("name","age"))
    
        # 查询yuan出版过的所有书籍的名字和价格
    
        #author_yuan=models.Author.objects.get(name="yuan")
    
        #print(author_yuan.book_set.all())  # 与这个作者关联的所有书籍对象
        #print(author_yuan.bookList.all().values("title","price"))
    
    一对一关系查询
    
      正向查询
    
        #查询手机号为456的作者的姓名
    
        # ad=models.AuthorDetail.objects.filter(tel="456").first()
        # print(ad.author.name)
    
    
        #detail_obj=models.AuthorDetail.objects.filter(tel="456").first()
        # print(detail_obj.author.name)#  与tel="456"的Author2Detail关联的作者对象
        #
        反向查询
        #  查询景丽洋的手机号
        # author_obj=models.AuthorA.objects.filter(name="景丽洋").first()
        # print(author_obj.author2detail.tel) # 789
        # print(author_obj.abc.tel) # 789    

    5.添加

    一对多的添加
        # 方式1
        #models.Book.objects.create(title="python",price=100,publishDate="2017-12-12",publish_id=1)
    
        # 方式2
        # pubObj=models.Publish.objects.filter(name="人民出版社")[0]
        # models.Book.objects.create(title="python2",price=120,publishDate="2017-10-12",publish=pubObj)  # 关联的出版社对象
    
    多对多的添加
        #book_obj=models.Book.objects.create(title="红楼梦", price=100, publishDate="2017-12-12", publish_id=2)
    
        # alex_obj=models.Author.objects.filter(name="alex")[0]
        # egon_obj=models.Author.objects.filter(name="egon")[0]
        # egon_obj=models.Author.objects.filter(name="yuan")[0]
        # print("======",book_obj.authorlist) # []
        # authorList=models.Author.objects.all()
        绑定多对多的关系
           # #book_obj.authorlist.add(alex_obj,egon_obj)  # [alex_obj,egon_obj]
        # book_obj.authorlist.add(*authorList)  # [alex_obj,egon_obj]
    
    
    解除多对多的关系
    
        # book_obj=models.Book.objects.filter(title="红楼梦").first()
        # authorList=models.Author.objects.filter(id__lt=3)
        # print(book_obj.authorlist.remove(*authorList))
    
    
    清除关系方法
        # book_obj = models.Book.objects.filter(title="红楼梦").first()
        # book_obj.authorlist.clear()

    五、聚合函数

    from django.db.models import Avg,Sum,Count,Max,Min
    
    聚合函数:aggregate
        # 查询所有图书的价格和
    
        ret=models.Book.objects.all().aggregate(priceSum=Sum("price"))
        ret=models.Book.objects.all().aggregate(priceAvg=Avg("price"),priceSum=Sum("price"))
        print(ret) # {'price__sum': Decimal('166.00')}
    
    分组函数 annote函数
    
        # 查询每一本书的作者个数
    
        book_list=models.Book.objects.all().annotate(c=Count("authorlist__name"))
        for book_obj in book_list:
            print(book_obj.c)
    
    
        # 查询每一个出版社出版过的最便宜的书籍
                ret=models.Book.objects.all().annotate(Min("price"))
            print(ret)
    统计不止一个作者的图书:
                 queryResult=Book.objects
              .annotate(num_authors=Count('authors'))
              .filter(num_authors__gt=1) 
    查询各个作者出的书的总价格:
    # 按author表的所有字段 group by
        queryResult=Author.objects
                  .annotate(SumPrice=Sum("book__price"))
                  .values_list("name","SumPrice") print(queryResult) #按authors__name group by queryResult2=Book.objects.values("authors__name")
                  .annotate(SumPrice=Sum("price"))
                  .values_list("authors__name","SumPrice") print(queryResult2)
    
    
    分组查询:
        querySet().annotate() --- 返回的是querySet
        
        #统计每一个出版社中最便宜的书籍的价格
        
        sql:
           select Min(price) from book group by publish_id;
        
        ORM:
        
        models.Book.objects.values("publish__name").annotate(Min("price"))

    六、F查询与Q查询

    F查询

    1.查询评论数大于收藏数的书籍:

     from django.db.models import F
       Book.objects.filter(commnetNum__lt=F('keepNum'))

    2. 查询评论数大于收藏数2倍的书籍

     Book.objects.filter(commnetNum__lt=F('keepNum')*2)

    3.修改操作也可以使用F函数,比如将每一本书的价格提高30元:

    Book.objects.all().update(price=F("price")+30) 

    Q查询

    filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q

     from django.db.models import Q

    Q(title__startswith='Py')
    bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))

    你可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:

    bookList=Book.objects.filter(Q(authors__name="yuan") & ~Q(publishDate__year=2017)).values_list("title")

    查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如:

    bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),
                                      title__icontains="python"
                                     )

     补充:

    有关Django中的命令:

    下载Django:pip3 install Django
              创建一个djang project:django-admin.py startptoject 项目名称;
              在目录下创建应用:python manage.py startapp blog;
              启动Django项目:python manage.py runserver 端口;
    
             python manage.py syncdb
    注意:Django 1.7.1 及以上的版本需要用以下命令
            python manage.py makemigrations
            python manage.py migrate

    '''
        python manage.py createsuperuser
         
        # 按照提示输入用户名和对应的密码就好了邮箱可以留空,用户名和密码必填
         
        # 修改 用户密码可以用:
        python manage.py changepassword username
        
    '''
    注意:
           对象可以调用自己的属性

     

  • 相关阅读:
    微软ReportViewer(rdlc)发布时所需要的动态库(vs2010)
    Jquery插件easyUI属性汇总
    利用ymPrompt的doHandler方法来实现获取子窗口返回值
    解决弹出的窗口window.open会被浏览器阻止的问题(自定义open方法)
    window.showModalDialog 内跳转页面的问题
    jquery中的ajax调用.net的ashx文件
    在RDLC报表中添加链接
    医学图像分析顶级会议
    人脑是如何认知图像的?
    【转】Mean Shift Code for the Edge Detection and Image SegmentatiON system
  • 原文地址:https://www.cnblogs.com/mengqingjian/p/7738595.html
Copyright © 2011-2022 走看看