Django规范化编程4

Task 10 原始数据库查询

虽然我们前面略微带过了数据库语句操作的部分,不过并不充分。Django中一共有3大使用原生sql查询的api, 分别是:

  • Queryset.raw()
  • Queryset.extra() (没用,过)
  • django.db.connection 数据库连接对象

先说Queryset.raw, 用法如下:

#直接在raw字段中写入数据库查询语句
m = PlayerEntity.objects.raw('SELECT ******')

这里m是返回的不再是QuerySet 对象, 而是RawQuerySet对象。

QuerySet 与 RawQueryset本身都可以看作是查询结果的迭代器,也就是说可以转为list的对象, 而且迭代的值都是我们的PlayEntity(或者你自己的model类), 可以从类中直接调用一条PlayEntity数据。不同的是,RawQueryset 没有values的接口将参数序列化为字典的接口。虽然,再render的local() 调用下没什么区别,不过直接从控制台获得信息稍加麻烦

此外RawQuerySet的查询结果必须包含主键保证记录的不通过(毕竟是Set 噗),所以查询时一定要带上主键

限制: 查询的字段必须是模型中声明的字段

而且每次查询结果为定义的模型类,即全数据获取,无法自定义浪费大量空间

其次了解下QuerySet.extra() 官方文档扫了一遍没找到,那就直接开冲。

# 先看参数,看参数我们就能搞个大概了
def extra(
        self,
        select=None,		* select的属性名
        where=None,			* 判断条件
        params=None,		
        tables=None,		* 表明
        order_by=None,		* 排序and排序顺序
        select_params=None,
    ):
# 这里所有的参数均以元组/数组传参。

extra返回的是QuerySet类型,感觉和raw好不了多少甚至一样拉。。。还是返回的整个类么,与上面raw的缺点没有变化。有点我个人感觉也没啥,(怪不得没文档) 原来可以用raw取代。

优点: 条理使用数组/元组更清晰

缺点: 容易搞蒙 + raw的所有

django.db.connections

创建一个连接数据库的对象(connection) 可以通过这个对象获取curson对象,再通过cursor的execute,fetchall, rowcount等方法执行原生的SQL获取结果

拓展,cursor是平时用pymysql最常见的游标操作器,需要自行学习,返回类型为元组

from django.db import connection
ursor = connection.cursor()
cursor.execute('Select * from player_Info')
k = cursor.fetchmany(2)
k
((1, 'Son_Bitch', 26, 38.7, None),(2, 'MyLover', 23, 14.4, None))
Task 10.5 models.Manager过滤覆写

我们直接找models.Manager()源码的时候发现只有一句pass。 为了完成我们的过滤或是其他的筛选条件,我们可以通过继承覆写的方式给我们的objects赋值或是做过滤器

# models.py
class Game_Filter(models.Manage):
    # 定义我们自己想要的方法,也可以覆写(我这里是获取已上架(代预售和已发售)的过滤器)
    def get_onsailgame(self):
        return super().get_queryset().filter(status__gte = 0)

class SomeEntity(models.Model):
    ...
    ...
    objects = Game_Filter()

# views.py
def try_filter():
    game = Gammer.objects.get_onsailgame().values()
    print(game)
    
# Python Console
from tryNew.views import try_filter
try_filter() # 这里我测试了,确实拿到过滤的结果了

一个简单的以status做过滤(status >=1)的过滤器就完成了。当然,如果你想在所有欲地方,如后台等视觉上均过滤不要的数据,覆写的方法(Game_Filter) 改成 get_queryset即可

过滤的方法把上面学的F, Q用起来~~

Task 11模型类的关联关系

(题外话:讲到模型关系,我就想到我们当时学的ER 和EER模型了。怎么说呢,老师讲的挺一般的导致我对数据库也没深挖下去的乐趣了)

模型与模型的对应关系:

https://www.cnblogs.com/chichung/p/9905835.html

  1. 一对一关系。 (不能双发一对一,不然合并不就行了么)
  2. 一对多关系
  3. 多对多关系

工具:Powerdesigner, 在大二下/数据库/其他/Powerdesigner

建立关系,我们需要进行对Entity进行其他Entity的引用,借用models的接口完成关系映射

eg. 这是一个我完善过的一个Game list表单

# 
class GamePlant(models.Model):
    # 主要是Pc Ns Xbox Ps
    game_plant = models.CharField(verbose_name="平台名称", max_length=30, primary_key=True)
    start_time = models.DateField(verbose_name="成立时间", null=True, blank=True)
    suppoert_chinese = models.IntegerField(verbose_name='支持情况', choices=((0, "不支持国区"), (1, "支持国区")), default=1)

    def __str__(self):
        return self.game_plant

    class Meta:
        db_table = 'games_plant'
        verbose_name = "游戏平台"
        verbose_name_plural = "游戏平台"


class GameMaker(models.Model):
    gamer_name = models.CharField(verbose_name='开发团队', max_length=100, null=False, blank=False, primary_key=True)
    gamer_location = models.CharField(verbose_name='团队位置', max_length=100, null=True, blank=True)
    gamer_num = models.IntegerField(verbose_name='团队人数', null=True, blank=True)

    def __str__(self):
        return self.gamer_name

    class Meta:
        db_table = 'games_gamer'
        verbose_name = "游戏厂商"
        verbose_name_plural = "游戏厂商"


# class Gammer(Game_Filter)
class Gammer(models.Model):
    name = models.CharField(verbose_name='游戏名称', max_length=50, null=False, blank=False)
    onsail_time = models.CharField(verbose_name='上市日期', max_length=15, default='敬请期待')
    price = models.IntegerField(verbose_name='价格', default=99999)
    image = models.ImageField(verbose_name='游戏封面', null=True, blank=True)
    author = models.ForeignKey(GameMaker, on_delete= models.CASCADE)
    # 这里不应该是外键一对多,而应该是多对多
    plantform = models.ManyToManyField(GamePlant)
    status = models.IntegerField(choices=((0, '未开启预购'), (1, '开启预购'), (2, '正式发售')), default=0)
    # 显性的创建查询结果集
    objects = models.Manager()

    def __str__(self):
        return self.name

    class Meta:
        db_table = 'games_info'
        verbose_name = '游戏之日'
        verbose_name_plural = verbose_name


这里面虽然没有一对一,但是因为实际情况确实比较少我就没搞。我把数据库中存放的表的状态给你拿出来:

在这里插入图片描述

我把关系列表给搞出来了, 很明显n…n在Django的接口使用两个1…n来搞定的,1…n 是很轻松的搞定的,所以说是看出来了Django的关系映射确实是不容小视。API的使用直接看上面的代码和教程即可,这里只是澄清多对多使用两个1对多的关系实现,就够了

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值