django操作数据库ORM

 
 

django 通过外键操作ORM

 
 

1.在模型层新建数据表


class
Country(models.Model): name = models.CharField(max_length=100) class Ctudent(models.Model): name = models.CharField(max_length=100) grade = models.PositiveIntegerField() country =models.ForeignKey(Country,on_delete=models.PROTECT)

导入数据:

from sales.models import *

c1 = Country.objects.create(name='中国')
c2 = Country.objects.create(name='美国')
c3 = Country.objects.create(name='法国')
Ctudent.objects.create(name='白月', grade=1, country=c1)
Ctudent.objects.create(name='黑羽', grade=2, country=c1)
Ctudent.objects.create(name='大罗', grade=1, country=c1)
Ctudent.objects.create(name='真佛', grade=2, country=c1)
Ctudent.objects.create(name='Mike', grade=1, country=c2)
Ctudent.objects.create(name='Gus', grade=1, country=c2)
Ctudent.objects.create(name='White', grade=2, country=c2)
Ctudent.objects.create(name='White', grade=2, country=c2)
Ctudent.objects.create(name='Napolen', grade=2, country=c3)

查询出学生名字为白月的所属国家

>>> s1 =Ctudent.objects.get(name='白月')
>>> s1.country.name

查询学生表里面一年级的学生

>>> Ctudent.objects.filter(grade=1).values()

查询出一年级的中国学生

>>> Ctudent.objects.filter(grade=1,country__name="中国").values()

指定字段显示查询一年级的中国学生

>>> Ctudent.objects.filter(grade=1,country__name="中国").values("name",'country__name')
<QuerySet [{'name': '白月', 'country__name': '中国'}, {'name': '大罗', 'country__name': '中国'}]>

给字段取别名

使用 annotate 方法

>>> Ctudent.objects.annotate(countryname=F('country__name'),studentname=F('name')).filter(grade=1,countryname="中国").values("studentname",'countryname')
<QuerySet [{'countryname': '中国', 'studentname': '白月'}, {'countryname': '中国', 'sname': '大罗'}]>

反向访问:

通过 表Model名转化为小写 ,后面加上一个 _set 来获取所有的反向外键关联对象

>>> cn.ctudent_set.all()

第二种实现反向访问的方法:

在定义Model的时候,外键字段使用 related_name 参数,像这样

class Country(models.Model):
    name = models.CharField(max_length=100)

class Ctudent(models.Model):
    name = models.CharField(max_length=100)
    grade = models.PositiveIntegerField()
    country =models.ForeignKey(Country,on_delete=models.PROTECT
                               ,related_name='ctudent')
>>> cn = Country.objects.get(name='中国')
>>> cn.ctudent.all()

反向过滤:

获得一年级学生的国家名

>>> Country.objects.filter(ctudent__grade=1).values()

去重

使用 .distinct() 去重

>>> Country.objects.filter(ctudent__grade=1).values().distinct()
<QuerySet [{'id': 1, 'name': '中国'}, {'id': 2, 'name': '美国'}]>

数据库事务:

场景:例如我们需要在一次操作找那个添加订单的操作,但是添加订单需要一般需要有订单表和商品订单表,这样我们添加一张订单的时候就需要执行两次数据库的操作,假如第一涨表添加成功时,请求又来了,所以又要执行一次添加请求操作,这样会让第二张表的数据丢失。为此我们需要引入数据库事务来进行控制,当第一张表添加后又来一次新的请求。当订单添加不成功时,数据库会有回滚事务。

django引入 with transaction.atomic() 来声明事务类型

def addorder(request):

    info  = request.params['data']

    # 从请求消息中 获取要添加订单的信息
    # 并且插入到数据库中

    
    with transaction.atomic():
        new_order = Order.objects.create(name=info['name'] ,
                                         customer_id=info['customerid'])

        batch = [OrderMedicine(order_id=new_order.id,medicine_id=mid,amount=1)  
                    for mid in info['medicineids']]
        OrderMedicine.objects.bulk_create(batch)


    return JsonResponse({'ret': 0,'id':new_order.id})

with transaction.atomic() 下面 缩进部分的代码,对数据库的操作,就都是在 一个事务 中进行了。

如果其中有任何一步数据操作失败了, 前面的操作都会回滚。

这就可以防止出现 前面的 Order表记录插入成功, 而后面的 订单药品 记录插入失败而导致的数据不一致现象。


大家可以发现 插入 OrderMedicine 表中的数据 可能有很多条, 如果我们循环用 ```py OrderMedicine.objects.create(order_id=new_order.id,medicine_id=mid,amount=1) ``` 插入的话, 循环几次, 就会执行 几次SQL语句 插入的 数据库操作 这样性能不高。

我们可以把多条数据的插入,放在一个SQL语句中完成, 这样会大大提高性能。

猜你喜欢

转载自www.cnblogs.com/Neotester/p/12965407.html
今日推荐