240      
    Alex   
  
    每个人都有属于自己的一片森林,也许我们从来不曾去过,但它一直在那里,总会在那里。迷失的人迷失了,相逢的人会再相逢!   

Django-model基础

ORM

映射关系:

ORM:object relationship mapping


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

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

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

创建表(建立模型)

数据库的迁移

python manage.py makemigrations    #数据库迁移
python manage.py migrate

创建数据库表字段

一、字段
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图片    upload_to='avatar/',保存图片的路径    default="/avatar/default.png"
24、models.FilePathField文件

class Meta:
  verbose_name_plural = "权限表"      #修改admin中显示表名字

二、字段参数
1、null=True
  数据库中字段是否可以为空
2、blank=True
  django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
  主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
  auto_now 自动创建---无论添加或修改,都是当前操作的时间
  auto_now_add 自动创建---永远是创建时的时间
5、choices
GENDER_CHOICE = (
(u'M', u'Male'),
(u'F', u'Female'),
)
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default  默认值
8、verbose_name  Admin中字段的显示名称
9、name|db_column  数据库中的字段名称
10、unique=True  不允许重复
11、db_index = True  数据库索引
12、editable=True  在Admin里是否可编辑
13、error_messages=None  错误提示
14、auto_created=False  自动创建
15、help_text  在Admin中提示帮助信息
16、validators=[]
17、upload-to               #保存文件的路径


    tags = models.ManyToManyField(
        to="Tag",
        through='Article2Tag',              #自定义创建多对多的表
        through_fields=('article', 'tag'),  #定义自定义表的字段
    )
建立一个图书管理系统
图书管理系统
1、创建表
  python manage.py makemigrations    #数据库迁移
#在/app01下面的models.py
from django.db import models

# Create your models here.

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

    python manage.py makemigrations    #数据库迁移
 #=======================================================华丽的分割线
#上面表创建之后会在app01/migrations下面自动添加了一个py文件 里面对应了创建的表,根据上面的类来区分,这只是第一步
  # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-25 11:45
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Book',
            fields=[
                ('nid', models.AutoField(primary_key=True, serialize=False)),
                ('title', models.CharField(max_length=32)),
                ('author', models.CharField(max_length=32)),
                ('publishDate', models.DateField()),
                ('price', models.DecimalField(decimal_places=2, max_digits=5)),
            ],
        ),
    ]
输出结果:
 第二步
python manage.py migrate
 
会生成一个
 第三步
在ORM/settings.py里面找到DATABASES这里是链接数据库的地方
添加
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'blog',    #你的数据库名称
        'USER': 'root',   #你的数据库用户名
        'PASSWORD': '', #你的数据库密码
        'HOST': '', #你的数据库主机,留空默认为localhost
        'PORT': '3306', #你的数据库端口

    }
在进行python manage.py makemigrations
**注意:这里会报错
 总结:报错 error loading MySQLdb module: No module named 'MySQLdb'.     
2版本支持mysqldb模块,3支持pymysql,为什么报这个错误,因为我现在没有告诉它我用的哪一个模块去走,默认是用mysqldb去走的,然后我用的3版本所以要告诉它我用pymysql就可以了
那么怎么弄呢
在app01应用下面添加pymysql就好了
import pymysql
pymysql.install_as_MySQLdb()
 这样在进行一次python manage.py migrate
 可以看到,已经插入进数据库了
那么现在要在前端页面上展示了
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
    <script src="/static/jquery-3.2.1.js"></script>
    <script src="/static/bootstrap-3.3.7/js/bootstrap.js"></script>
</head>
<body>
<div class="container-fluid">
    <!-- Button trigger modal -->
    <a href="/add/"><button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">添加</button></a>
    <table class="table table-hover table-bordered">
        <tr>
            <td>编号</td>
            <td>书名</td>
            <td>作者</td>
            <td>日期</td>
            <td>价格</td>
            <td>操作</td>
        </tr>
        #通过for循环来
        {% for foo in book_list %}
            <tr>

                <th>{{ foo.nid }}</th>
                <th>{{ foo.title }}</th>
                <th>{{ foo.author }}</th>
                <th>{{ foo.publishDate|date:"Y-m-d" }}</th>
                <th>{{ foo.price }}</th>
                <th>
                    <a href="{{ foo.nid }}">
                        <button class="btn btn-success">修改</button>
                    </a>
                    <a href="/del/{{ foo.nid }}">
                        <button class="btn btn-danger">删除</button>
                    </a>
                </th>

            </tr>
        {% endfor %}
    </table>
</div>
</body>
</html>



#==================================================我是华丽的分割线
from django.shortcuts import render,redirect

from app01 import models
# Create your views here.


def index(request):
    #从数据库取出来的数据
    book_list=models.Book.objects.all()
    return render(request,"index.html",{"book_list":book_list})


#删除
def deltitle(request,id):
    models.Book.objects.filter(nid=id).delete()
    return redirect("/index/")

#添加
def add(request):
    if request.method=="POST":
        name=request.POST.get("name")
        bookname = request.POST.get("bookname")
        author=request.POST.get("author")
        time=request.POST.get("time")
        price=request.POST.get("price")
        models.Book.objects.create(nid=name,title=bookname,author=author,publishDate=time,price=price)
        return redirect("/index/")
    return render(request,"add.html")
 添加
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <div class="form-group">
        <label for="exampleInputEmail1">编号</label>
        <input type="text" class="form-control" id="exampleInputEmail1" name="name">
    </div>
    <div class="form-group">
        <label for="exampleInputPassword1">书名</label>
        <input type="text" class="form-control" id="exampleInputPassword1" name="bookname">
    </div>
    <div class="form-group">
        <label for="exampleInputPassword1">作者</label>
        <input type="text" class="form-control" id="exampleInputPassword1" name="author">
    </div>
    <div class="form-group">
        <label for="exampleInputPassword1">时间</label>
        <input type="date" class="form-control" id="exampleInputPassword1" name="time">
    </div>
    <div class="form-group">
        <label for="exampleInputPassword1">价格</label>
        <input type="text" class="form-control" id="exampleInputPassword1" name="price">
    </div>
    <div>
        <a href="/add/"><button>提交</button></a>
    </div>
</form>
</body>
</html>
输出结果:
 logging
通过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',
        },
    }
}
示例:把上面的logging放入settings.py里面
 当前端添加数据放入数据库时会进行数据库的操作,这样可以清晰的看到数据库做了什么操作了
 

注意事项:

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

字段选项

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

一旦你建立好数据模型之后,django会自动生成一套数据库抽象的API,可以让你执行关于表记录的增删改查的操作。

添加表记录

普通字段


1.添加数据库的两种方式:

from django.shortcuts import render,redirect

from app01 import models
# Create your views here.


def index(request):
    #从数据库取出来的数据
    book_list=models.Book.objects.all()
    return render(request,"index.html",{"book_list":book_list})



def deltitle(request,id):
    models.Book.objects.filter(nid=id).delete()
    return redirect("/index/")


def add(request):
    if request.method=="POST":
        name=request.POST.get("name")
        bookname = request.POST.get("bookname")
        author=request.POST.get("author")
        time=request.POST.get("time")
        price=request.POST.get("price")
    '''   
    添加数据库的两种方式
    '''
        #方式一:
        # models.Book.objects.create(nid=name,title=bookname,author=author,publishDate=time,price=price)
        # 方式二
        book_obj=models.Book(nid=name,title=bookname,author=author,publishDate=time,price=price)
        book_obj.save()
        return redirect("/index/")
    return render(request,"add.html")

2.修改数据库的两种方式

from django.shortcuts import render ,HttpResponse,redirect

from app01 import models

# Create your views here.

def index(request):

    # 从数据库取出所有书籍对象

    bookList=models.Book.objects.all()  # QuerySet数据类型   [bookObj1,.....]


    return render(request,"index.html",{"bookList":bookList})


def delBook(request,id):

    models.Book.objects.filter(nid=id).delete()

    return redirect("/index/")


def editBook(request):

    if request.method=="POST":
        id=request.POST.get("book_id")

        # 修改方式1:save(效率低)
        # book_obj=models.Book.objects.filter(nid=id)[0]
        # book_obj.title="东京不太热"
        # book_obj.save()

        # 修改方式2:
        title=request.POST.get("title")
        author=request.POST.get("author")
        pubDate=request.POST.get("pubDate")
        price=request.POST.get("price")


                                           models.Book.objects.filter(nid=id).update(title=title,author=author,publishDate=pubDate,price=price)


        return redirect("/index/")

    id = request.GET.get("book_id")
    print("id", id)
    edit_book=models.Book.objects.filter(nid=id)[0]  #    [obj1,]


    return render(request,"edit.html",{"edit_book":edit_book})

外键字段

    # 一对多的添加
    # 方式一
    # models.Publish.objects.create(name="五道口职业技术出版社",addr="北京")
    # models.Book.objects.create(title="东京有点热",publishdate="2017-11-11",price=99,publish_id=1)
    # return HttpResponse("OK")
    # 方式二
    # pubobj=models.Publish.objects.filter(name="五道口职业技术出版社")[0]
    # models.Book.objects.create(title="东京不太热",publishdate="2017-11-11",price=99,publish=pubobj)
    # print(pubobj.addr)
示例:
#models.py

from django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    publishdate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)
    publish=models.ForeignKey("Publish")                          #建立一对多的表关系



class Publish(models.Model):
    name=models.CharField(max_length=32)
    addr=models.CharField(max_length=32)
    
    # 一对多的添加
    # 方式一
    # models.Publish.objects.create(name="五道口职业技术出版社",addr="北京")
    # models.Book.objects.create(title="东京有点热",publishdate="2017-11-11",price=99,publish_id=1)
    # return HttpResponse("OK")
    # 方式二
    # pubobj=models.Publish.objects.filter(name="五道口职业技术出版社")[0]                    # 关联的出版社对象
    # models.Book.objects.create(title="东京不太热",publishdate="2017-11-11",price=99,publish=pubobj)
    # print(pubobj.addr)
    

输出结果:
 

多对多字段

   bookobj=models.Book.objects.create(title="红楼梦",author="alex",publish="东莞出版社",publishdate="2017-10-27",price=99,publish_contrast_id=2)
    alex_obj=models.Author.objects.filter(name="alex")[0]
    print(alex_obj)
    print(bookobj.authorlist)
    # authorLish=models.Author.objects.all()
    bookobj.authorlist.add(alex_obj)

1、添加多对多的关系

book_obj.authorlist.add(alex_obj,egon_obj)            #将某个特定的 model 对象添加到被关联对象集合中。
book_obj.authorlist.add(*authorList)                  #通过某个特定的model集合对象添加到被关联对象集合中

2、解除多对多的关系

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

3、清空多对多的关系

book_obj.authors.clear()  




查询表记录

查询相关API


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

<15> defer                 
注意:一定区分object与querySet的区别 !!!
示例:
def query(request):
    # 查询方法API:


    #1  all: models.表名.objects.all()

    book_all=models.Book.objects.all()  # 结果是querySet集合    [model对象,....]
    #print(book_all) # <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]>

    # 2 filter: models.表名.objects.filter() # 结果是querySet集合    [model对象,....]

    # ret1=models.Book.objects.filter(author="yuan") # # <QuerySet [<Book: 追风筝的人>, <Book: asd>]>
    #ret2=models.Book.objects.filter(nid=1) # <QuerySet [<Book: yuan>]>
    # ret2=models.Book.objects.filter(author="yuan",price=123) # <QuerySet [<Book: yuan>]>
    # print(ret2)

    # 3 get  models.表名.objects.get()   # model对象

    # ret3=models.Book.objects.get(author="yuan")
    # print(ret3.price)


    # exclude : 排除条件
    # ret4=models.Book.objects.exclude(author="yuan")
    # print(ret4)

    # values方法
    # ret=models.Book.objects.filter(author="yuan").values("title","price")
    # print(ret)# <QuerySet [{'title': '追风筝的人', 'price': Decimal('99.00')}, {'title': 'asd', 'price': Decimal('123.00')}]>

    # ret = models.Book.objects.filter(author="yuan").values_list("title", "price")
    # print(ret) # <QuerySet [('追风筝的人', Decimal('99.00')), ('asd', Decimal('123.00'))]>

    # ret=models.Book.objects.filter(author="yuan").values("author").distinct()
    # print(ret)

    # count方法
    # ret=models.Book.objects.filter(author="yuan").count()
    # print(ret)

    # first 方法
    # ret = models.Book.objects.all().first()
    # print(ret)

    # exists方法
    # if models.Book.objects.all().exists():
    #     print("exists")
    # else:
    #     print("nothing")



    ret=models.Book.objects.filter(price__gt=100)
    ret=models.Book.objects.filter(price__gte=99) # 大于等于

    #ret=models.Book.objects.filter(publishDate__year=2017,publishDate__month=10)
    #ret=models.Book.objects.filter(author__startswith="张")


    print(ret)
    return HttpResponse("OK")

******重点注意QuerySet对象和objcet对象

Django ORM用到三个类:Manager、QuerySet、Model。Manager定义表级方法(表级方法就是影响一条或多条记录的方法),我们可以以models.Manager为父类,定义自己的manager,增加表级方法;QuerySet:Manager类的一些方法会返回QuerySet实例,QuerySet是一个可遍历结构,包含一个或多个元素,每个元素都是一个Model 实例,它里面的方法也是表级方法,前面说了,Django给我们提供了增加表级方法的途径,那就是自定义manager类,而不是自定义QuerySet类,一般的我们没有自定义QuerySet类的必要;django.db.models模块中的Model类,我们定义表的model时,就是继承它,它的功能很强大,通过自定义model的instance可以获取外键实体等,它的方法都是记录级方法(都是实例方法,貌似无类方法),不要在里面定义类方法,比如计算记录的总数,查看所有记录,这些应该放在自定义的manager类中

queryset对象

pubobj=models.Book.objects.all()       #这是queryset对象通过queryset调用API的方法

object对象

pubobj=models.Book.objects.filter(title="东京有点热").first()   #拿到关联字段的对象
print(pubobj.price)                 #这样就可以通过.来调用字段获取字段的信息
输出结果:
 

数据库表查询

表结构
from django.db import models

# Create your models here.


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)
    wordNum=models.IntegerField(default=0)
    readNum=models.IntegerField(default=0)


    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()
    author_detail=models.OneToOneField("AuthorDetail")         #一对一关系
    def __str__(self):
        return self.name

class AuthorDetail(models.Model):
    tel=models.IntegerField()
    addr=models.CharField(max_length=32)




一对一关系的查询

        #一对一查询
        #正向查询 按字段
           # 一对一关系查询
            # # 查询egon的手机号
    author_obj=models.Author.objects.filter(name="egon").first()
    print(author_obj.author_detail.tel) 
    #反向查询   按表名
    #查询手机号为456的作者的姓名
    author_de=models.AuthorDetail.objects.filter(tel="456").first()
    print(author_de)
    print(author_de.author.name)
 




一对多关系的查询

    # 一对多的查询
    # 查询linux这本书的出版社的地址?
    #正向查询 按字段
    book_obj=models.Book.objects.get(title="linux")     #get方式
    print(book_obj)
    print(book_obj.publish.addr)
    或者  
    book_obj=models.Book.objects.filter(title="linux").first()        #filter方式
    print(book_obj)
    print(book_obj.publish.addr)
    #反向查询
    # 人民出版社出版过的书籍的名字
        #按related_name别名来查询
    publish_obj=models.Publish.objects.filter(name="人民出版社").first()
    print(publish_obj.bookList.all())
    
    
    
        


多对多关系的查询

    # 多对多的查询
    #正向查询   按字段
    # 查询追风筝的人的所有作者的姓名和年龄
    book_obj=models.Book.objects.filter(title="python红宝书")[0]
    authorlist=book_obj.authorlist.all()       #与这本书关联的所有作者对象,集合对象 <QuerySet [<Author: alex>, <Author: egon>, <Author: eva>]>
    print(authorlist)
    print(authorlist.values("name"))
    #反向查询   按related_name别名查询
    # 查询yuan出版过的所有书籍的名字和价格  
    author_yuan=models.Author.objects.get(name="alex")
    # print(author_yuan.Book_set.all())  # 与这个作者关联的所有书籍对象
    print(author_yuan.bookList.all().values("title","price"))    





双下划线之单表查询

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.一对一关系的查询

    # 查询linux这本书的出版社的地址?
    #正向查询  #按字段
    print(models.Book.objects.filter(title="python红宝书").values("publish__addr")) #通过__来进行跨表查询
    # 查询人民出版社出版过的所有书籍的名字与价格
    #反向查询 按related_name别名查询
    print(models.Publish.objects.filter(name="人民出版社").values("bookList__title","bookList__price"))
    

2.多对多关系的查询

    #查询egon出过的所有书籍的名字(多对多)
    #反向   按related_name别名查询
    print(models.Author.objects.filter(name="egon").values("bookList__title"))
    #正向 按照字段查询
    #查询linux是哪个作者写的
    ret=models.Book.objects.filter(title="linux").values("authorlist__name")
    print(ret)

3.一对一关系的查询

    #正向查询 #按字段
       #作者为egon的手机号
    ret=models.Author.objects.filter(name="egon").values("author_detail__tel")
    print(ret)
    
    #反向查询 按表名
    #手机号为456的作者
    ret=models.AuthorDetail.objects.filter(tel="456").values("author__name")
    print(ret)
    
    
    

4.多表联合查询

    # 手机号以151开头的作者出版过的所有书籍名称以及出版社名称
    方法一:反向查询
    ret=models.AuthorDetail.objects.filter(tel__startswith="151").first()  #__startswith 以内容开头
    print(ret)
    print(ret.author.bookList.all().values("title","publish__name"))       
    方法二:
      # 方法2正向查询
        ret=models.Book.objects.filter(authorlist__author_detail__tel__startswith="151").values("title","publish__name")
    print(ret)

聚合查询与分组查询

导入聚合函数的和分组查询的模块
from django.db.models import Avg,Sum,Count,Max,Min

聚合:aggregate(*args, **kwargs)

聚合函数:aggregate
# 查询所有图书的价格和
    ret=models.Book.objects.all().aggregate(priceSum=Sum("price"))     #pruceSum自定义名字,如果没加的话会默认加上名字
    print(ret)
输出结果:
    '''
    {'priceSum': Decimal('166.00')}

    '''

分组:annotate() 

# 分组函数 annote函数

 # 查询每一本书的作者个数

  book_list=models.Book.objects.all().annotate(c=Count("authorlist__name"))
  for book_obj in book_list:
      print(book_obj.c)










F查询与Q查询

F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

示例:
from django.shortcuts import render,HttpResponse

from app01 import models

# Create your views here.




def login(request):
    return render(request,"login.html")


def index(request):
    obj=models.Admin.objects.filter(commentNumb__gt=200).values("id")     #可以通过整数来定义查询条件但是却不能按相同方法比较数据库中的字段
    print(obj)
    return HttpResponse("OK")
解决方法:
from django.shortcuts import render,HttpResponse

from app01 import models

# Create your views here.
#必须要导入F
from django.db.models import F,Q


def login(request):
    return render(request,"login.html")


def index(request):
    #查询评论数小于阅读数的字段
    obj=models.Admin.objects.filter(commentNumb__lt= F('readNumb')).values("id")
    # 查询评论数大于收藏数2倍的书籍
    Book.objects.filter(commnetNum__lt=F('keepNum')*2)
    
    #修改操作也可以使用F函数,比如将每一本书的价格提高30元:

    Book.objects.all().update(price=F("price")+30)
    print(obj)
    return HttpResponse("OK")
数据库
 输出结果:可以看到输出两个
 

Q查询

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

from app01 import models

# Create your views here.
from django.db.models import F,Q


def login(request):
    return render(request,"login.html")


def index(request):
    # obj=models.Admin.objects.filter(commentNumb__lt= F('readNumb')).values("id")
    #查询name=chenyang and name=egon的书籍
    obj = models.Admin.objects.filter(Q(name="chenyang")|Q(name="egon")).values("title")
    print(obj)
    return HttpResponse("OK")
数据库
 输出结果:
 

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

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

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


















 
 






posted @ 2017-10-26 00:40  Alex_c  阅读(193)  评论(0编辑  收藏  举报