mysql、MongoDB、Django-SQL、Redis日常操作

常规数据库操作:
基础命令
        show databases;
            查看当前有哪些数据库
        select database();
            查看当前数据库的名字
        use mysql;
            切换数据库为mysql
        show tables;
            查看当前数据库中有哪些表
        select * from user\G;
            查看user表中所有的数据

创建数据库
            语法:create database 数据库名字;

数据的新增
    字符类型必须加单引号,日期类型也是
    数字类型数据直接使用
    列的数据类型和值得数据类型必须一致
    d1.向表中所有列新增数据
        语法:insert into 表 values (值1,值2...);
        CREATE TABLE emp(
            ename CHAR(10),
            age   INT,
            birth DATE
        );
        INSERT INTO emp VALUES('neimaer',20,'2000-09-08');
    d2.向表中指定列新增数据
        语法:insert into 表(列1,列2...) values(值1,值2...);
        向emp表中新增数据,员工名字为outman,age为18
        insert into emp(ename,age) values('outman',18);
    d3.补充
        新增多条数据
        INSERT INTO emp(ename) VALUES('a'),('b'),('c');
e.数据的修改(更新)
    字符类型必须加单引号,日期类型也是
    数字类型数据直接使用
    列的数据类型和值得数据类型必须一致
        语法:update 表 set 列=值 [where 条件];
        修改满足条件的数据
        修改emp表中名字为outman的年龄修改为88
        update emp set age=88 where ename='outman';
        修改整个列的数据
        如果不加where条件,默认修改的是整个列的值
        修改emp表中所有年龄为0
        update emp set age=0;
f.数据的删除
    f1.delete和truncate区别
        delete     DML(数据库操作语言) 可以删除指定数据 删除数据可以找回
        truncate   DDL(数据库定义语言) 只能删除所有数据 删除数据无法找回
    f2.delete
        语法:delete from 表 [where 条件];
        删除emp表中名字为outman的所有数据
        delete from emp where ename='outman';
        删除emp表中所有数据
        delete from emp;
    f3.truncate
        语法:truncate table 表名;
        删除emp表中所有数据
        truncate table emp;
g.表结构的删除
    语法:drop table 表名;
    删除emp表结构
    drop table emp;

补充:
    删除表结构中的某个列:alter table 表 drop column 列名
        ALTER TABLE txl DROP COLUMN tel;
    修改表结构中的某个列:change
        alter table 表 modify 列 数据类型 约束
        ALTER TABLE txl MODIFY NAME INT;
    表结构中新增一列
        alter table 表 add 列 数据类型
        ALTER TABLE txl ADD tel CHAR(20);
数据的查询 
    h1.分类
        简单查询
        多表查询
        子查询
        分组查询
    h2.简单查询
        查询时候可以查询指定行,指定列,指定行的列
        语法:select 列 from 表 [where 条件];
        查询演员表中名字是NICK的所有信息
        SELECT * FROM actor WHERE first_name='NICK';
        查询演员表中所有人的姓氏和名字
        select last_name,first_name from actor;
        查询演员表中所有名字是NICK的人的姓氏
        select last_name from actor where first_name='NICK';
    h3.where条件
        1>比较
            >
            <
            =
            >=
            <=
            !=
            <>   不等于
        查询演员表中名字不是NICK的所有数据
        select * from actor where first_name !='NICK';
        查询演员表中演员id小于20的所有信息
        select * from actor where actor_id<20;
        2>逻辑
            and  同时满足条件
            or   满足一个条件即可
            not  不满足条件
        查询演员表中名字是NICK的并且演员id小于20的所有信息
        select * from actor where first_name='NICK' and actor_id<20;
        查询演员表中名字是NICK或者SMITH的所有信息
        select * from actor where first_name='NICK' or first_name='SMITH';
        3>空置(null)
            空没有任何数据类型,没有任何值,不能用于比较和运算
            查询时候使用is null或者is not null
        查询演员表中名字为空的所有信息
        select * from actor where first_name is null;
        4>in
            在...里面(或的关系)
        查询演员表中名字是NICK或者SMITH的所有信息
        select * from actor where first_name in ('NICK','SMITH');
        5>模糊查询
            通常是和字符类型一起使用,当信息不完整时候使用
            like
            _   一个字符
            %   任意个字符
        查询演员表中名字是N开头的所有信息
        select * from actor where first_name like 'N%';
        查询演员表中名字是K结尾的所有信息
        select * from actor where first_name like '%K';
        查询演员表中名字是4个字符的所有信息
        select * from actor where first_name like '____';
        SELECT * FROM actor WHERE first_name LIKE '%C%';
        6>区间查询
        between ... and ...包括两个端点
        查询演员表中演员id范围在2030之间的所有信息
        select * from actor where actor_id >= 20 and actor_id<=30;
        select * from actor where actor_id between 20 and 30;


语法:
create table 表(
    列1 数据类型 [constraint 约束名] primary key,
    列2 数据类型 unique,
    列3 数据类型 not null,
    列4 数据类型 check(列4的条件),
    列5 数据类型 references 被参考表(被参考列)
);

create table test(
    id int primary key,
    name char(10) unique,
    age  int  not null,
    sex  char(10) check(sex='male' or sex='famale')
);

1.笛卡尔积(集)
    两张表不做任何关联所产生的数据
    select * from city;
    select * from country;
    select * from city,country;
    笛卡尔积会使数据量成倍增加,产生很多无效数据,为了避免此类型情况,使用内联、左联、右联查询
    左联:
        语法: select 列 from1 left join 表2 on 表1.列=表2.列;
        左联出来的结果:内联查询结果+左表中有,右表中没有,右表中对应位置为空(左表中所有数据都有)
    右联:
        语法:select 列 from1 right join 表2 on 表1.列=表2.列;(右表中所有数据都有)
    SELECT * FROM a LEFT JOIN b ON a.id=b.it;
    SELECT * FROM a RIGHT JOIN b ON a.id=b.it;
2.内联查询
    关联列判断方法
        a.列名相同
        b.作用相同
        c.主外键关系
    语法:
    select 列 from1 ,表2 where 表1.列=表2.列;
    select 列 from1 inner join 表2 on 表1.列=表2.列;


    查询city名称为Acua的国家名称
    a.分析列
        城市名称
        国家名称
    b.分析表
        城市名称  city
        国家名称  country
    c.关联
        select * from city,country
        where city.country_id=country.country_id;
    d.过滤
        select country from city,country
        where city.country_id=country.country_id
        and city='Acua';

    查询city名称为Acua的国家名称,country_id
    c.关联
        select * from city c,country c1
        where c.country_id=c1.country_id;
    d.过滤
        select c1.country,c.country_id from city c,country c1
        where c.country_id=c1.country_id
        and c.city='Acua';

分组查询
1.分组
    按照某种属性进行分类
2.分组函数(聚合)
    max    最大
    min    最小
    avg    平均
    sum    求和
    count  计数
    分组函数通常是和分组一起使用,也可以单独使用
    查询付款表中最高付款金额,最低付款金额,平均付款金额
    select max(amount),min(amount),avg(amount) from payment;
3.分组查询
    语法:select 列 from 表
            [where 条件]
                group by 分组条件
                    [having 分组后过滤条件]
    分组条件判断
        每后面跟的就是分组条件
    select后面from前面的列如果要显示必须是分组条件
    查询每个国家有多少个城市?要求显示国家名字和城市数量
    a.分析列
        国家名字
        城市名字
    b.分析表
        国家 country
        城市 city
    c.关联
        select * from city c,country co
        where c.country_id=co.country_id;
    d.过滤
        select  co.country,count(c.city) from  city c,country co
        where c.country_id=co.country_id
        group by co.country;

4.分组后过滤
    先分组后过滤
    where   分组前过滤 不能直接跟分组函数
    having  分组后过滤 后面可以直接跟分组函数
    查询哪些国家的城市超过20个?
    select  co.country,count(c.city) from  city c,country co
    where c.country_id=co.country_id
    group by co.country
    having count(c.city)>20;

查询客户表中每种名字有多少人?
select u.name,count(u.name)
from kehu k, user u
where kehu.name = user.name
group by u.name
查询每个城市有多少个地址?
===============================================================

SQL:结构化查询语言
   DDL:数据库定义语句   create alter drop truncate
   DML:数据库操作语句   insert delete update
   DCL:数据库控制语句   grant revoke
   DQL:数据库查询语句   select

子查询(嵌套)
一条SQL语句的执行依赖于另外一条SQL语句的执行结果
查询国家名称是China的城市有哪些?
select city from city where country_id=(select country_id from country where country='china')
a.列
    国家
    城市
b.表
    国家 country
    城市 city
c.关联的列
    country_id
d.拆分需求
    d1.查询国家表中国家名称是China的country_id
        select country_id from country where country='China';
    d2.查询城市表中country_id为上面查询出来结果的城市名称
        select city from city where country_id=(select country_id from country where country='China');

1.排序
语法:
    select 列 from 表
        where 条件
            group by 分组条件
                having 分组后过滤条件
                    order by 排序条件;
a.顺序
    从小到大
    order by 列
    order by 列 asc
    查询actor表中所有数据,按照actor_id从小到大进行排列
    select * from actor order by actor_id;
b.逆序
    从大到小
    order by 列 desc
    查询actor表中所有数据,按照actor_id从大到小进行排列
    select * from actor order by actor_id desc;

补充:双排序,多排序
    SELECT * FROM city ORDER BY country_id,city_id DESC;

2.limit
    limit 分页查询
    查询actor 表中前3条数据
    SELECT * FROM actor LIMIT 3
    查询actor表中第4到第8条数据
    SELECT * FROM actor LIMIT 3,5
学会排序,灵活运用很关键,可顺序取前十,倒序取倒十
笔试题
1.insert into student values('小明','005');
2.update exam set score=85 where code=(select code from student where name='李四') and subject='语文';
3.select  subject,avg(score)  from exam group by subject
4.select s.name,s.code,a.score from student s right join exam a
on s.code=a.code order by s.code,a.subject;


5.

    a>查询每个科目最高分
        select max(score),subject from exam group by subject;
    b>查询每门成绩最高的学生id
        select a.code from exam a,(select max(score) s1,subject from exam group by subject) b
        where a.subject=b.suject
        and a.score=b.s1
    c>select    s.name,s.code,a.suject,a.score  from student s,exam a
            where s.code=a.code
            and s.code in (
                select a.code from exam a,(select max(score) s1,subject from exam group by subject) b
                    where a.subject=b.suject
                        and a.score=b.s1
                        )
********************************************************************************************************
1.mongodb

a.基础
    数据分为2部分:软件、数据
    数据库是由集合组成
    集合是由文档组成
     mysql      mongodb
     数据库     数据库
     表         集合
     数据       文档
b.mongodb的服务
    mongod   mongodb的主服务
    mongo    mongodb的客户端服务
    27107    mongodb的端口
    b1.服务的检查
        win+r--cmd--tasklist | find "mongod"
    b2.端口的检查
        win+r--cmd--netstat -an | find "27017"
c.mongodb的登陆
    c1.登陆命令
        mongo
            登陆本地数据库
        mongo 127.0.0.1
            登陆ip为127.0.0.1的数据库
        mongo 127.0.0.1:27017/admin
            登陆ip为127.0.0.1端口为27107的admin数据库
    c2.登陆方式
        1>进入到命令所在位置
        2>设置环境变量
d.mongodb的基础命令
    show databases
    show dbs
        查看当前有哪些数据库
    db
        查看当前数据库的名字
    use local
        数据库切换为local
    show tables
    show collections
        查看当前数据库有哪些集合
    db.startup_log.find()
        查看startup_log集合中所有文档
e.CURD(增删改查)
    e1.文档新增
        db.xiyouji.insert({name:'5kong',age:18})
    e2.文档查询
        db.xiyouji.find({age:18})
    e3.文档修改
        db.xiyouji.update({age:18},{$set:{name:'tangsir'}})
    e4.文档删除
        db.xiyouji.remove({name:'8jie'})
f.文档新增
    f1.新增普通文档
        db.xiyouji.insert({name:'tai2'})
     f2.新增文档指定_id
        db.xiyouji.insert({_id:0,name:'kingkong'})
     f3.新增内嵌文档
        db.xiyouji.insert({name:'skong',jingli:{kill:500,hit:1}})
       f4.新增多个文档
            db.xiyouji.insert([{name:'tieshan'},{name:'niumo'}])
g.文档的查询
    g1.查询所有文档
        db.xiyouji.find()
    g2.查询指定文档
        db.xiyouji.find({age:{$exists:1}})
    g3.查询指定文档的指定属性
        db.xiyouji.find({name:"5kong"},{_id:0,name:1})
     g4.查询表达式
        1>比较
            &gt                   >
            &gte                  >=
            &lt                   <
            &lte                  <=
            &ne                   !=
            db.xiyouji.find({age:{&gte:20}})
            db.xiyouji.find({age:{&ne:20}})
         2 > 关系
            &and            同时满足
            db.xiyouji.find({&and:[{age:{&lte:20}},{name:'yudi'}]},{_id:0})
            &or              满足一个即可
            db.xiyouji.find({&or:[{age:{&lte:20}},{name:'yudi'}]})
         3 > 存在性
            $exists         属性存在与否
            db.xiyouji.find({age:{$exists:1}})
h.文档的更新
    h1.替换全部文档
        db.xiyouji.update({name:'tangsir'}, {age:666})
    h2.修改指定文档($set)
        db.xiyouji.update({name:'tangsir'}, {$set:{age:100}})
    h3.删除属性($unset)
        db.xiyouji.update({name:'tangsir'}, {$unset:{age:100}})
    h4.增长列
        db.xiyouji.update({name:'tangsir'}, {$inc:{age:100}})(age + 100)
 i.文档的删除
    i1.删除指定文档
        db.xiyouji.remove({age:{$exists:1}})
    i2.删除所有文档
        db.xiyouji.remove()


**************************************************************************************************************
redis详解:http://www.cnblogs.com/yuhangwang/p/5817930.html
第二链接:https://blog.csdn.net/liqingtx/article/details/60330555
/*************************************************************************************************************
网站参考:https://www.cnblogs.com/slfenng/p/7880734.html
python——Django(ORM连表操作)https://www.cnblogs.com/Eva-J/p/5373414.html
python——Django(ORM连表操作)进阶 https://www.cnblogs.com/happy-king/p/8338404.html

 用 ./manage.py shell 打开交互式环境,在其中为模型添加一条记录,时间使用当前时间,
 当前时间通过django.utils.timezone.now() 来获取

    from app1.models import Log
    from django.utils import timezone
    log = Log(time=timezone.now())
    log.save()


Django模型的部分API使用范例

# 创建新记录

>>> a = Author(name='Alice', age=18)
>>> a.save()
>>> a = Author.object.create(name='Alice', age=18)

创建新记录的常见方法:
    1. a = Author(name='Alice', age=18)
       a.save()
    2. a = Author()
       a.name = 'Alice'
       a.age = 18
       a.save()
    3. a = Author.objects.create(name='Alice', age=18)


# 删除记录

>>> e.delete()
(1, {'weblog.Entry': 1})
>>> Entry.objects.filter(pub_date__year=2005).delete()
(5, {'webapp.Entry': 5})


# 修改记录
>>> a = Author.objects.get(name='Alice', age=18)
>>> a.age += 1
>>> a.save()
>>> Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

# Change every Entry so that it belongs to this Blog.
>>> b = Blog.objects.get(pk=1)
>>> Entry.objects.all().update(blog=b)


# 查询记录

通过模型的Manager可以获得一个QuerySet,通过QuerySet可以查询数据库记录,每一个模型都有一个Manager,它的名字默认是objects。

>>> Entry.objects.all()                             # 获取模型的所有记录
>>> Entry.objects.filter(pub_date__year=2006)       # 抽取符合条件的记录
>>> Entry.objects.exclude(pub_date__year=2006)      # 排除符合条件的记录

串接过滤条件

>>> Entry.objects.filter(
...     headline__startswith='What'
... ).exclude(
...     pub_date__gte=datetime.date.today()
... ).filter(
...     pub_date__gte=datetime.date(2005, 1, 30)
... )

QuerySet 的特点

1. 每一个QuerySet都是独一的,互相之间是独立的,以下q1, q2是两个独立的QuerySet
    q1 = Entry.objects.filter(headline__startswith="What")
    q2 = q1.exclude(pub_date__gte=datetime.date.today())
2. QuerySet是惰性的,意思是到“最后一刻”才会操作数据库,下面四条语句,到print语句时才真正操作数据库
    q = Entry.objects.filter(headline__startswith="What")
    q = q.filter(pub_date__lte=datetime.date.today())
    q = q.exclude(body_text__icontains="food")
    print(q)


获取一条记录,使用get方法,get方法支持和filter一样的表达式:

>>> one_entry = Entry.objects.get(pk=1)

如果没有匹配的记录,或者有超过一条的记录,get方法会抛出异常。


限制结果集大小

>>> Entry.objects.all()[:5]     # 返回QuerySet,不操作数据库
>>> Entry.objects.all()[5:10]   # 返回QuerySet,不操作数据库
>>> Entry.objects.all()[:10:2]  # 用了step, 操作数据库,返回list


对结果排序

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

此语句先按pub_date反序排,然后按照headline顺序排。



按字段做过滤

在字段名和操作符之间用两个下划线分隔:

    Book.objects.filter(name__contains='Python')

操作符的详细用法请参考
https://docs.djangoproject.com/en/1.11/ref/models/querysets/#field-lookups


<1> all():                 查询所有结果

<2> filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

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

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

<4> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                           model的实例化对象,而是一个可迭代的字典序列
                            # This list contains a Blog object.
                            >>> Blog.objects.filter(name__startswith='Beatles')
                            <QuerySet [<Blog: Beatles Blog>]>

                            # This list contains a dictionary.
                            >>> Blog.objects.filter(name__startswith='Beatles').values()
                            <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
                            >>> Blog.objects.values('id', 'name')
                            <QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

<9> values_list(*field, flat=False):
                            它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
                            >>> Entry.objects.values_list('id').order_by('id')
                            <QuerySet[(1,), (2,), (3,), ...]>

                            >>> Entry.objects.values_list('id', flat=True).order_by('id')
                            <QuerySet [1, 2, 3, ...]>

<6> order_by(*field):      对查询结果排序
                            Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
                            上面的结果将按pub_date降序排序,然后按 headline升序排序。前面的负号"-pub_date"表示 降序。升序是隐含的。
                            要随机订购,请使用"?",如下:
                            Entry.objects.order_by('?')

<7> reverse():             对查询结果反向排序
                            要检索查询集中的“最后”五个项,您可以执行以下操作:
                            my_queryset.reverse()[:5]
                            上面的例子将首先返回最后一项,然后是倒数第二项,依此类推。
                            请注意,reverse()通常只应在具有QuerySet 已定义排序的情况下调用(例如,在查询定义默认排序的模型时或使用时order_by())。
                            如果没有为给定定义这样的排序QuerySet,则调用reverse()它没有实际效果(在调用之前排序是未定义的reverse(),
                            并且之后将保持未定义)。

<8> distinct():            从返回结果中剔除重复纪录
                            Entry.objects.order_by('pub_date').distinct('pub_date')

<10> count():              返回数据库中匹配查询(QuerySet)的对象数量。
                            Entry.objects.filter(headline__contains='Lennon').count()

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

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

<13> exists():             如果QuerySet包含数据,就返回True,否则返回False
                            entry = Entry.objects.get(pk=123)
                            if some_queryset.filter(pk=entry.pk).exists():
                                print("Entry contained in queryset")

<14> aggregate():           返回通过计算的聚合值(平均值,总和等)的字典QuerySet
                            >>> from django.db.models import Count, Avg, Max, Min, Sum
                            >>> q = Blog.objects.aggregate(Count('entry'))
                            {'entry__count': 16}

<17> annotate():            为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

                            (1) 练习:统计每一本书的作者个数

                            bookList=Book.objects.annotate(authorsNum=Count('authors'))
                            for book_obj in bookList:
                                print(book_obj.title,book_obj.authorsNum)

                             练习:统计每一个出版社的最便宜的书

                           方式一:

                            publishList=Publish.objects.annotate(MinPrice=Min("book__price"))

                            for publish_obj in publishList:
                                print(publish_obj.name,publish_obj.MinPrice)

                            annotate的返回值是querySet,如果不想遍历对象,可以用上valuelist:

                            queryResult= Publish.objects.annotate(MinPrice=Min("book__price")).values_list("name","MinPrice")
                                                                             
                            print(queryResult)

                            方式二:

                            queryResult=Book.objects.values("publish__name").annotate(MinPrice=Min('price'))


<15> update(** kwargs):     对指定的字段执行SQL更新查询,并返回匹配的行数(如果某些行已具有新值,则可能不等于更新的行数
                            要关闭2010年发布的所有博客条目的注释,您可以执行以下操作:
                            >>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)

<16> delete():              对其中的所有行执行SQL删除查询
                            例如,要删除特定博客中的所有条目:

                            >>> b = Blog.objects.get(pk=1)

                            # Delete all the entries belonging to this Blog.
                            >>> Entry.objects.filter(blog=b).delete()
                            (4, {'weblog.Entry': 2, 'weblog.Entry_authors': 2})



可用的操作符:

1. exact                精确匹配: polls.get_object(id__exact=14).
2. iexact               忽略大小写的精确匹配: polls.objects.filter(slug__iexact="foo") 匹配 foo, FOO, fOo, 等等.
3. contains             大小写敏感的内容包含测试: polls.objects.filter(question__contains="spam")
                        返回question 中包含 "spam" 的所有民意测验.
                        (仅PostgreSQL 和 MySQL支持. SQLite 的LIKE 语句不支持大小写敏感特性. 对Sqlite 来说, contains 等于 icontains.)
4. icontains            大小写不敏感的内容包含测试:
5. in                   在给定的列表中。
                        Entry.objects.filter(id__in=[1, 3, 4])
                        您还可以使用查询集动态评估值列表,而不是提供文字值列表:
                        inner_qs = Blog.objects.filter(name__contains='Cheddar')
                        entries = Entry.objects.filter(blog__in=inner_qs)
                        == SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

6. gt                   >                       Entry.objects.filter(id__gt=4)
7. gte                  >=
8. lt                   <
9. lte                  <=
10. startswith          区分大小写的开头            Entry.objects.filter(headline__startswith='Lennon')
11. istartswith         不区分大小写的开头
12. endswith            区分大小写的结尾
13. iendswith           不区分大小写的结尾
14. range               范围测试(包括在内)
                        import datetime
                        start_date = datetime.date(2005, 1, 1)
                        end_date = datetime.date(2005, 3, 31)
                        Entry.objects.filter(pub_date__range=(start_date, end_date))
15. date                将字符串转化为日期类型
                        Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
16. year                Entry.objects.filter(pub_date__year=2005)
17. month
18. day
19. week
                        Entry.objects.filter(pub_date__week=52)
                        Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)
20. week_day            对于日期和日期时间字段,“星期几”匹配。
                        Entry.objects.filter(pub_date__week_day=2)
21. time
22. hour
23. minute
24. second
25. isnull
26. regex               区分大小写的正则表达式匹配。
                        Entry.objects.get(title__regex=r'^(An?|The) +')
27. iregex              不区分大小写的正则表达式匹配。
28. search              布尔全文搜索,利用全文索引。
                        Entry.objects.filter(headline__search="+Django -jazz Python")


Q()对象

from django.db.models import Q

Book.objects.filter(Q(pages__gte=10)|Q(price__lt=100))


Q对象的更多用法 (Query)

and: Q(pk=1) & Q(pk=2)
or: Q(pk=1) | Q(pk=2)
not: ~Q(pk=1)

from django.db.models import Q
condition = Q(pk__lt=100) & Q(pk__gt=50)
M.objects.filter(condition)


F()对象
以下操作:

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()

可以换成:

from django.db.models import F

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()

通过 F() 可以引用数据表中的字段,这样,该字段的值不会从数据库读入Python中,Python也无从知晓该字段的值,加一的操作完全在数据库内容执行,效果等同于:

update reporter set stories_filed = stories_filed + 1;

用这种方式更新的记录,需要重载该记录,才能看到新的值:

reporter = Reporters.objects.get(pk=reporter.pk)
# 或者这样:
# reporter.refresh_from_db()

F() 可以用在QuerySet对象的update方法上,见避免了get()和save()操作:

reporter = Reporters.objects.filter(name='Tintin')
reporter.update(stories_filed=F('stories_filed') + 1)


F() 可以提升性能:

1. 让数据库做计算操作,而不是让python来做
2. 减少某些操作的查询次数




Django 提供了三种模型之间的关系,分别是:

1. 多对一(一对多),通过ForeignKey 实现
2. 多对多,通过ManyToManyField 实现
3. 一对一,通过OneToOneField 实现

这三种关系本质上都是通过外键 (foreign key) 来实现的。



创建多对一关系

以父子关系为例,一个父亲可以有多个孩子,一个孩子只能有一个父亲,父亲是“一”,孩子是“多”。

class Father(models.Model):
    name = models.CharField(max_length=128)

class Child(models.Model):
    name = models.CharField(max_length=128)
    father = models.ForeignKey(Father)


通过多对一关系获取关联的记录

f1 = Father.objects.create(name="Abraham")
f2 = Father.objects.create(name="Isaac")
c1 = Child.objects.create(name="Isaac", father=f1)
c2 = Child.objects.create(name="Ishmael", father=f1)
c3 = Child.objects.create(name="Esau", father=f2)
c4 = Child.objects.create(name="Israel", father=f2)

通过Father 记录获取关联的Child 记录:

In [14]: f1.child_set.all()
Out[14]: <QuerySet [<Child: Child object>, <Child: Child object>]>

通过Child 记录获取关联的Father 记录:

In [15]: c1.father
Out[15]: <Father: Father object>

使用关联记录作为查询条件:

In [19]: Father.objects.get(child=c1)
Out[19]: <Father: Father object>

In [20]: Father.objects.get(child=c1.pk)
Out[20]: <Father: Father object>

In [21]: Father.objects.filter(child__in=[c1,c2])
Out[21]: <QuerySet [<Father: Father object>, <Father: Father object>]>

In [22]: Father.objects.filter(child__name='Israel')
Out[22]: <QuerySet [<Father: Father object>]>

In [23]: Child.objects.filter(father__name='Abraham')
Out[23]: <QuerySet [<Child: Child object>, <Child: Child object>]>


多对一关系中删除操作的影响

1. 默认情况下,删除“一”中的记录,“多”中的相关记录会被删除。删除“多”中的记录不影响“一”中的记录。
2. 如果需要改变关联删除这种行为,可以在定义ForeignKey 的时候传递一个 on_delete=models.DO_NOTHING 的参数。

    on_delete=models.DO_NOTHING 这种设定,视后台的数据库的不同,行为也会不一样。以mysql为例,
    就算手动给mysql的数据表添加了 ON DELETE NO ACTION后,依然不能删除“一”中的记录;不过,如果
    使用on_delete=models.SET_NULL,然后在mysql数据表上设置外键属性 ON DELETE SET NULL后,就
    可以正常删除“一”中的记录,“多”中的记录的外键会被自动设置为null(就是pyhton的None)。



多对多关系

创建多对多关系

以文章和标签为例,一篇文章可以使用多个标签,一个标签可以给多篇文章使用,是多对多的关系。

class Tag(models.Model):
    desc = models.CharField(max_length=128)

class Article(models.Model):
    title = models.CharField(max_length=128)
    tag = models.ManyToManyField(Tag)


通过多对多关系获取关联的记录

In [22]: t1 = Tag.objects.create(desc='Linux')
In [23]: t2 = Tag.objects.create(desc='Python')
In [24]: a1 = Article.objects.create(title='Python on Linux is good')
In [25]: a2 = Article.objects.create(title='Python on Linux is powerful')
In [26]: a1.tag.add(t1, t2)
In [27]: a2.tag.add(t1, t2)

通过Tag 记录获取关联的Article 记录:

In [28]: t1.article_set.all()
Out[28]: <QuerySet [<Article: Article object>, <Article: Article object>]>

通过Article 记录获取关联的Tag 记录:

In [29]: a1.tag.all()
Out[29]: <QuerySet [<Tag: Tag object>, <Tag: Tag object>]>

使用关联记录作为查询条件:

In [30]: Tag.objects.filter(article__in=[a1, a2])   <-- 有重复
Out[30]: <QuerySet [<Tag: Tag obje   ct>, <Tag: Tag object>, <Tag: Tag object>, <Tag: Tag object>]>

In [31]: Tag.objects.filter(article__in=[a1, a2]).distinct() <-- 去重
Out[31]: <QuerySet [<Tag: Tag object>, <Tag: Tag object>]>

In [32]: Article.objects.filter(tag__in=[t1.pk, t2]).distinct()
Out[32]: <QuerySet [<Article: Article object>, <Article: Article object>]>

In [33]: Article.objects.filter(tag__desc__startswith='L').distinct()
Out[33]: <QuerySet [<Article: Article object>, <Article: Article object>]>


多对多关系中删除操作的影响

删除多对多关系中任何一边的记录,不会连带删除另外一边的记录。




一对一关系

创建一对一关系

以非对称加密系统中的公钥和私钥为例。实践中,一个公钥唯一匹配一个私钥,一个私钥唯一匹配一个公钥,是一对一的关系。

class Private(models.Model):
    keyid = models.CharField(max_length=128)


class Public(models.Model):
    keyid = models.CharField(max_length=128)
    private = models.OneToOneField('Private', null=True)


通过一对一关系获取关联的记录

In [2]: pri1 = Private.objects.create(keyid='a')

In [3]: pri2 = Private.objects.create(keyid='b')

In [4]: pub1 = Public.objects.create(keyid='c', pravite=pri1)

In [5]: pub2 = Public.objects.create(keyid='d', pravite=pri2)

通过Private 记录获取关联的Public 记录:

In [32]: pri1.public
Out[32]: <Public: Public object>

通过Public 记录获取关联的Private 记录:

In [33]: pub1.private
Out[33]: <Private: Private object>

使用关联记录作为查询条件:

In [34]: Public.objects.get(private=pri1)
Out[34]: <Public: Public object>

In [35]: Public.objects.filter(private__in=[pri1,pri2])
Out[35]: <QuerySet [<Public: Public object>, <Public: Public object>]>

In [36]: Private.objects.filter(public=pub1.pk)
Out[36]: <QuerySet [<Private: Private object>]>


一对一关系中删除操作的影响

一对一关系本质上是外键关系(和多对一关系一样),只不过一对一关系给外键加上唯一性限制而已。两个模型的定义中,没有OneToOneField 的那个模型可以被称为“被引用”的模型。默认情况下,删除“被引用”的模型的记录,会连带删除对应的“引用”模型的记录,在定义OneToOneField 时加上on_delete=models.DO_NOTHING 可以改变连带删除行为。删除“引用”模型的记录则不会删除“被引用”模型的记录。这和“一对多”关系是一样的。






















四、创建指定时区的时间对象,并对时间做时区转换
1. 用pytz.timezone 创建一个Asia/Chongqing 的时区
    from datetime import datetime
    import pytz
    tz = pytz.timezone('Asia/Chongqing')    <-- 创建时区
2. 给一个没有时区信息的时间加上刚创建的时区信息
    naive_time = datetime.now()             <-- 无时区信息
    aware_time = tz.localize(naive_time)    <-- 加上本地时区信息
    # aware_time = datetime.now(tz)         <-- 给now加上时区参数,效果与上面两条命令等价
3. 把加上时区信息的时间对象转换成UTC的时间
    tz2 = pytz.timezone('UTC')              <-- 另外一个时区
    tz2.normalize(aware_time)               <-- 时区转换
    aware_time.astimezone(tz2)              <-- 时区转换,与上等价







sqlite命令行操作参考

    .help           <-- 显示帮助信息
    .tables         <-- 显示所有表的名字
    .schema         <-- 显示所有表的结构
    .schema tb1     <-- 显示表db1的结构
    .header on
    .mode column
    select * from tb1



定制Django后台,关联编辑

假设Choice通过ForeignKey指向Question,现在需要在编辑Question的时候能够编辑相关联的Choice,
则可以参考以下做法:

# 定义一个Inline的类,类中用model属性指明被关联编辑的模型,这里就是Choice
class ChoiceStackInline(admin.TabularInline):
    model = Choice

# 定义一个ModelAdmin类,类中用inlines来使用刚刚定义好的Inline类
class ChoiceAdmin(admin.ModelAdmin):
     inlines = [ChoiceStackInline,]

# 注册的时候,把刚刚定义好的ModelAdmin类作为第二个位置参数
admin.site.register(Question, ChoiceAdmin)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值