[实验] Django 实现数据原子性

注意:

本实验是接着 《Django 自定义逻辑添加(通过自定义 save 对象实现)(一次性完成多对多表数据的插入)》而继续的

正文:

将 mysite/user/models.py 中的以下内容:

class Clazz(models.Model):
    cname = models.CharField(max_length=30)

class Student(models.Model):
    sname = models.CharField(max_length=30)
    score = models.PositiveBigIntegerField()
    cls = models.ForeignKey(Clazz,on_delete=models.CASCADE)

    def __str__(self):
        return u'Student:%s,%s'%(self.sname,self.score)

    def  save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        try:
            self.cls = Clazz.objects.get(cname=self.cls.cname)
        except Clazz.DoesNotExist:
            self.cls = Clazz.objects.create(cname=self.cls.cname)

        #Insertion of student table
        models.Model.save(self, force_insert=False, force_update=False,using=None, update_fields=None)

修改为:

class Clazz(models.Model):
    cname = models.CharField(max_length=30)

class Student(models.Model):
    sname = models.CharField(max_length=30)
    score = models.PositiveBigIntegerField()
    cls = models.ForeignKey(Clazz,on_delete=models.CASCADE)

    def __str__(self):
        return u'Student:%s,%s'%(self.sname,self.score)

    from django.db.transaction import atomic
    @atomic
    def  save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        try:
            self.cls = Clazz.objects.get(cname=self.cls.cname)
        except Clazz.DoesNotExist:
            self.cls = Clazz.objects.create(cname=self.cls.cname)

        #Insertion of student table
        models.Model.save(self, force_insert=False, force_update=False,using=None, update_fields=None)

[实验] Django 数据修改

注意:

本实验是接着 《Django 最大值、最小值、平均值等特殊数值的数据查询》而继续的

正文:

步骤一:进入相应的 Django 环境

(django_env) [root@python mysite]# python3
>>> import os,django
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
>>> django.setup()
>>> from user.models import *

步骤二:导入数据修改 F 模块

>>> from django.db.models import Q,F

(补充:这里同时也倒入了 Q 模块,后面的实验会用到 Q 模块)

步骤三:设置一个显示上一句 SQL 语句的函数

>>> def showsql():
...     from django.db import connection
...     print(connection.queries[-1]['sql'])
... 

步骤四:进行数据修改

4.1 单独修改某 1 条数据

4.1.1 单独修改某 1 条数据
>>> Student.objects.filter(id=3).update(score=F('score')+5)
1


补充:
1) 这里以给 id 等于 3 的数据的 score 值添加 5 为例
2) 这里共修改了 1 条数据

4.1.2 显示单独修改某 1 条数据 SQL 语句
>>> showsql()
UPDATE `user_student` SET `score` = (`user_student`.`score` + 5) WHERE `user_student`.`id` = 3

(补充:这里以给 id 等于 3 的数据的 score 值添加 5 为例)

4.2 批量修改数据

4.2.1 批量修改数据
>>> Student.objects.filter(Q(id__gt=3)).update(score=F('score')+5)
3


补充:
1) 这里以给 id 大于 3 的数据的 score 值添加 5 为例
2) 这里共修改了 3 条数据

4.2.2 显示批量修改数据的 SQL 语句
>>> showsql()
UPDATE `user_student` SET `score` = (`user_student`.`score` + 5) WHERE `user_student`.`id` > 3

(补充:这里以给 id 大于 3 的数据的 score 值添加 5 为例)

补充:get 无法对获得的结果进行操作

>>> Student.objects.get(id=3).update(score=33)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'update'


补充:
1) 前面 filter 返回结果是 QuerySet,所以可以被 update 操作
2) 现在 get 的返回结果是 1 个对象,所以不能被 update 操作

[实验] Django 逻辑条件数据查询

注意:

本实验是接着 《Django 最大值、最小值、平均值等特殊数值的数据查询》而继续的

正文:

步骤一:进入相应的 Django 环境

(django_env) [root@python mysite]# python3
>>> import os,django
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
>>> django.setup()
>>> from user.models import *

步骤二:导入逻辑条件查询 Q 模块

>>> from django.db.models import Q

步骤三:设置 1 个显示上 1 句 SQL 语句的函数

>>> def showsql():
...     from django.db import connection
...     print(connection.queries[-1]['sql'])
... 

步骤四:进行逻辑条件查询

4.1 Django 进行与查询

4.1.1 通过 Q 查询进行与查询
4.1.1.1 通过 Q 查询进行与查询
>>> Student.objects.filter(Q(sname='lisi')&Q(score=80))
<QuerySet [<Student: Student:lisi,80>]>


补充:
1) 这里以查询同时满足 sname=’lisi’ 条件和 score=80 条件的数据为例
2) 这里共查询到了 1 条数据

4.1.1.2 显示通过 Q 查询进行与查询的 SQL 语句
>>> showsql()
SELECT `user_student`.`id`, `user_student`.`sname`, `user_student`.`score`, `user_student`.`cls_id` FROM `user_student` WHERE (`user_student`.`sname` = 'lisi' AND `user_student`.`score` = 80) LIMIT 21

(补充:这里以查询同时满足 sname=’lisi’ 条件和 score=80 条件的数据为例)

4.1.2 通过 filter 进行与查询
4.1.2.1 通过 filter 进行与查询
>>> Student.objects.filter(sname='lisi',score=80)
<QuerySet [<Student: Student:lisi,80>]>


补充:
1) 这里以查询同时满足 sname=’lisi’ 条件和 score=80 条件的数据为例
2) 这里共查询到了 1 条数据

4.1.2.2 显示通过 filter 进行与查询的 SQL 语句
>>> showsql()
SELECT `user_student`.`id`, `user_student`.`sname`, `user_student`.`score`, `user_student`.`cls_id` FROM `user_student` WHERE (`user_student`.`score` = 80 AND `user_student`.`sname` = 'lisi') LIMIT 21

(补充:这里以查询同时满足 sname=’lisi’ 条件和 score=80 条件的数据为例)

4.2 Django 进行或查询

4.2.1 通过 Q 查询进行或查询
>>> Student.objects.filter(Q(sname='zhangsan')|Q(score=90))
<QuerySet [<Student: Student:zhangsan,60>, <Student: Student:wangwu,90>]>


补充:
1) 这里以查询同时满足 sname=’lisi’ 条件或 score=90 条件的数据为例
2) 这里共查询到了 1 条数据

4.2.2 显示通过 Q 查询进行或查询的 SQL 语句
>>> showsql()
SELECT `user_student`.`id`, `user_student`.`sname`, `user_student`.`score`, `user_student`.`cls_id` FROM `user_student` WHERE (`user_student`.`sname` = 'zhangsan' OR `user_student`.`score` = 90) LIMIT 21

(补充:这里以查询同时满足 sname=’lisi’ 条件或 score=90 条件的数据为例)

4.3 Django 进行非查询

4.3.1 通过 Q 查询进行非查询
>>> Student.objects.filter(~Q(sname='zhangsan'))
<QuerySet [<Student: Student:lisi,80>, <Student: Student:wangwu,90>, <Student: Student:zhaoliu,70>, <Student: Student:xueer,70>, <Student: Student:huangyi,70>]>


补充:
1) 这里以查询 sname=’zhangsan’ 条件不成立的数据为例
2) 这里共查询到了 5 条数据

4.3.2 显示通过 Q 查询进行非查询的 SQL 语句
>>> showsql()
SELECT `user_student`.`id`, `user_student`.`sname`, `user_student`.`score`, `user_student`.`cls_id` FROM `user_student` WHERE NOT (`user_student`.`sname` = 'zhangsan') LIMIT 21

(补充:这里以查询 sname=’zhangsan’ 条件不成立的数据为例)

4.4 Django 进行与非组合查询

4.4.1 通过 Q 查询进行与非组合查询
>>> Student.objects.filter(~Q(sname='zhangsan',score=90))
<QuerySet [<Student: Student:zhangsan,60>, <Student: Student:lisi,80>, <Student: Student:wangwu,90>, <Student: Student:zhaoliu,70>, <Student: Student:xueer,70>, <Student: Student:huangyi,70>]>


补充:
1) 这里以查询同时满足 sname=’lisi’ 条件和 score=80 条件不成立的数据为例
2) 这里共查询到了 1 条数据

4.4.2 显示通过 Q 查询进行与非组合查询的 SQL 语句
>>> showsql()
SELECT `user_student`.`id`, `user_student`.`sname`, `user_student`.`score`, `user_student`.`cls_id` FROM `user_student` WHERE NOT (`user_student`.`score` = 90 AND `user_student`.`sname` = 'zhangsan') LIMIT 21

(补充:这里以查询同时满足 sname=’lisi’ 条件和 score=80 条件不成立的数据为例)

[实验] Django 自定义一个数据查询函数

注意:

本实验是接着 《Django 最大值、最小值、平均值等特殊数值的数据查询》而继续的

正文:

步骤一:进入相应的 Django 环境

(django_env) [root@python mysite]# python3
>>> import os,django
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
>>> django.setup()
>>> from user.models import *

步骤二:自定义 1 个查询对象

>>> def test(sql):
...     from django.db import connection
...     with connection.cursor() as c:
...         c.execute(sql)
...         for info in c.fetchall():
...             print(info)
...

(补充:这里以自定义名为 test 的自定义查询对象为例)

步骤三:使用自定义查询对象查询数据

>>> test('select * from user_clazz')
(1, 'Class1')
(2, 'Class2')


补充:这里以
1) 使用 test 对象
2) 执行 select * from user_clazz SQL 语句
3) 查询结果是 1 Class1,2 Class2 两条数据
为例

[实验] Django 通过 SQL 语句进行数据查询

注意:

本实验是接着 《Django 最大值、最小值、平均值等特殊数值的数据查询》而继续的

正文:

步骤一:进入相应的 Django 环境

(django_env) [root@python mysite]# python3
>>> import os,django
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
>>> django.setup()
>>> from user.models import *

步骤二:Django SQL 语句完全查询

>>> user = Student.objects.raw('select * from user_student')
>>> for s in user:
...     print(s)
... 
Student:zhangsan,60
Student:lisi,80
Student:wangwu,90
Student:zhaoliu,70
Student:xueer,70
Student:huangyi,70

(补充:这里以查看 user_student 表中的所有数据为例)

步骤三:Django SQL 语句部分查询

3.1 导入 Django SQL 语句部分查询的模块

>>> from django.db import connection

3.2 Django SQL 语句部分查询(含主键查询)

3.2.1 创建游标(含主键查询)
>>> cur = connection.cursor()

(补充:这里以创建名为 cur 的游标为例)

3.2.2 查询数据并导入游标(含主键查询)
>>> cur.execute('select * from user_student')
6


补充:
1) 这里以查询 user_student 表里到所有数据并导入 cur 游标为例
2) 这里查出的数据总共有 6 条

3.2.3 将游标里的数据导入到变量里(含主键查询)
>>> cs = cur.fetchall()

(补充:这里以将数据导入到 cs 变量里为例)

3.2.4 将游标里的数据以对象的形式显示出来(含主键查询)
>>> print(cs)
((1, 'zhangsan', 60, 1), (2, 'lisi', 80, 1), (3, 'wangwu', 90, 1), (4, 'zhaoliu', 70, 1), (5, 'xueer', 70, 2), (6, 'huangyi', 70, 2))

(补充:这里显示出来的是对象)

3.2.5 将游标里的数据以列表的形式显示出来(含主键查询)
>>> for c in cs:
...     print(c)
... 
(1, 'zhangsan', 60, 1)
(2, 'lisi', 80, 1)
(3, 'wangwu', 90, 1)
(4, 'zhaoliu', 70, 1)
(5, 'xueer', 70, 2)
(6, 'huangyi', 70, 2)

(补充:这里打出来的是列表)

3.2.6 关闭游标(含主键查询)
>>> cur.close()

(补充:这里以关闭 cur 游标为例)

3.3 Django SQL 语句部分查询(不包含主键)

3.3.1 创建游标(不包含主键)

>>> cur = connection.cursor()

(补充:这里以创建名为 cur 的游标为例)

3.3.2 查询数据并导入游标(不包含主键)

>>> cur.execute('select sname,score from user_student')
6


补充:
1) 这里以查询 user_student 表里 sname 字段和 socre 字段的所有数据并导入 cur 游标为例
2) 这里查出的数据总共有 6 条

3.3.3 将游标里的数据导入到变量里(不包含主键)
>>> cs = cur.fetchall()

(补充:这里以将数据导入到 cs 变量里为例)

3.3.4 将游标里的数据以对象的形式显示出来(不包含主键)
>>> print(cs)
(('zhangsan', 60), ('lisi', 80), ('wangwu', 90), ('zhaoliu', 70), ('xueer', 70), ('huangyi', 70))

(补充:这里显示出来的是对象)

3.2.5 将游标里的数据以列表的形式显示出来(不包含主键)
>>> for c in cs:
...     print(c)
... 
('zhangsan', 60)
('lisi', 80)
('wangwu', 90)
('zhaoliu', 70)
('xueer', 70)
('huangyi', 70)

(补充:这里显示出来的是列表)

3.2.5 关闭游标(不包含主键)
>>> cur.close()

(补充:这里以关闭 cur 游标为例)

3.3 Django SQL 语句部分查询(只查询 1 条数据)

3.3.1 创建游标(只查询 1 条数据)
>>> cur = connection.cursor()

(补充:这里以创建名为 cur 的游标为例)

3.3.2 查询数据并导入游标(只查询 1 条数据)
>>> cur.execute('select * from user_clazz where id=1')
1


补充:
1) 这里以查询 user_clazz 表里 id 字段的值为 1 为例
2) 这里查出的数据总共有 1 条

3.3.4 将游标里的数据以对象的形式显示出来(只查询 1 条数据)
>>> cur.fetchone()
(1, 'Class1')

(补充:这里显示出来的是列表)

3.2.5 关闭游标(只查询 1 条数据)
>>> cur.close()

(补充:这里以关闭 cur 游标为例)