学习django心得(一)

学习django心得(一)

说明:该文章用于博主记录学习心得和主要学习收获,学习材料大多来自刘江的博客教程,本文也就是它教程的概括,感兴趣的同学可以前往学习(ps:常见API原博客教程解释得很详细)

时间:2020/3/1
学习内容:Django的模型层

Django采用的架构模式的核心是MVC,即Model View Controller,分别对应着模型、视图、控制器三个层次架构,其中模型层就对应着web应用后端需要使用的数据库,django的ORM(对象关系映射)保证了python用户可以不去直接使用SQL语言操作数据库,而在django界面直接用python创建对象的方式来生成构建数据库。整体实现过程是python代码通过ORM自动转换为SQL语句,再通过pymysql来实际操作数据库,通过这我们就知道了模型其实就是对应着数据库。因此接下来就让我们一起来学习django模型层的相关操作。(如果决定Django的模型操作语句过于复杂,允许直接使用SQL操作数据库)

创建表

Django中使用类来创建表,也就是说你再model文件中创建了一个类,再在该类中赋予其一定的属性,就构成了一个有值的表,例如:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

这几行代码创建了一个Person类,对应数据库中就创建了一个Person表

模型字段

常用模型字段
CharField 表示固定长字符串数据类型
IntegerField 整数类型
AutoField 自动增加的整数类型
DateField 日期类型
DateTimeField 日期时间类型
DecimalField 固定精度小数类型
FileField 上传文件类型
TextField 大量文本类型

完整性约束语句

外键:
1、多对一:
class ForeignKey(to, on_delete, **options)[source]

例:

from django.db import models

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'Manufacturer',
        on_delete=models.CASCADE,
    )
    # ...

class Manufacturer(models.Model):
    # ...
    pass

重要参数解释:

  • to:对应的其他表的属性
  • on_delete:一旦被外键关联的对象被删除,要如何进行操作

on_delete选项:

  • CASCADE:将定义有外键的模型对象同时删除
  • PROTECT:不删除定义有外键的模型对象,但是抛出ProtectedError异常
  • SET_NULL:将外键字段设为null
  • SET_DEFAULT:将外键字段设为默认值
  • DO_NOTHING:与我无关,啥也不做
  • SET():设置为一个传递给SET()的值或者一个回调函数的返回值。
2、多对多:
class ManyToManyField(to, **options)[source]

从字面意思上不难理解他的用处

3、一对一:
class OneToOneField(to, on_delete, parent_link=False, **options)[source]
主键:

primary_key
例:

from django.db import models
class Fruit(models.Model):
    name = models.CharField(max_length=100, primary_key=True)
unqiue:

表示该字段数据在整个表中不可重复
可取值:True / False

null:

可取值:True / False
默认取值:False
取值为True时数据库用NULL保存空值

db_index:

取值为True时,数据库为该字段创建索引

元数据Meta

元数据是指“除字段外的所有内容”,添加方法是在模型类中添加一个子类,名字固定是Meta,然后在子类中设置各种选项参数
例:

from django.db import models

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:         
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"
Meta部分可用参数
  • abstract:设置为True时模型被认为是一个抽象模型
  • app_label:声明其属于哪个app
  • db_table:指定在数据库中该模型的表名
  • db_tablespace:自定义数据库表空间名
  • ordering:指定该模型生成的所有对象的排序方式
  • unique_together:可用于设置该表中哪些字段是不可重复的
  • verbose_name:用于设置模型对象的直观名称,支持中文

模型继承

类似python类的继承方式,在Django的模块中也有继承,继承的方式有如下三种:

  • 抽象基类:父类定义为抽象模型(在数据库中不会实际建表),供子类继承重用
  • 多表继承:每个模型都有自己的数据库表,父类就是正常的模型
  • 代理模型:
抽象基类:

在Meta类里添加abstract=True就表示该类为抽象类
例:

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

需要注意:
子类会继承父类所有数据字段,包括Meta类中的属性,如果子类有相同字段不同设定可以覆盖,子类可以添加字段,父类的abstract=True字段不会被继承
如果父类存在外键并且有related_name,related_query_name参数,如果原样继承会出错,因此一般在这两个参数值中包含%(app_label)s 和 %(class)s:

  • %(class)s用字段所属子类的小写名替换
  • %(app_label)s用子类所属app的小写名替换
    例:
from django.db import models

class Base(models.Model):
    m2m = models.ManyToManyField(
    OtherModel,
    related_name="%(app_label)s_%(class)s_related",
    related_query_name="%(app_label)s_%(class)ss",
    )

    class Meta:
        abstract = True

class ChildA(Base):
    pass

class ChildB(Base):
    pass
多表继承

父类和子类都是独立自主的模型
多表继承中,子类不会继承父类的Meta类,ordering和get_latest_by参数除外
需要注意:
django会自动在父类和子类之间建立一个默认的一对一关联,因此可以通过父类访问子类,与此同时,在创建外键的时候也要指定related_name,否则就会与隐式存在的一对一外键重名

代理模型

只改变python层面的行为而不改变数据库,也就是说子类和父类公用一张数据库表,并且父类和子类可以通过对方访问
添加方式:在子类的Meta类中proxy=True,即可表示是代理模型继承
需要注意的是父类不能是抽象基类

补充说明:
  • 支持多重继承
  • 非抽象基类的继承不允许覆盖,即子类不能设定父类的字段

查询操作

检索所有对象:all()

all_entries = Entry.objects.all()

条件查询:filter() 或 exclude()
filter 返回根据条件得到的QuerySet
exclude 返回条件得到的QuerySet的补集

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

注意:得到的QuerySet可以被单独保存

检索单一对象: get()

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

可以直接得到单个对象,但如果查询结果不是单一对象则会抛出异常

QuerySet:
类似python中列表类型,可以当作列表来使用,不同点是QuerySet不能使用负索引

常见查询API:

使用方法:属性+双下划线+API名
exact: 默认类型

Blog.objects.get(id__exact=14)

iexact: 不区分大小写

Blog.objects.get(name__iexact="beatles blog")

contains: 包含,大小写敏感

Entry.objects.get(headline__contains='Lennon')

icontains: 包含,大小写不敏感
startswith和endswith: 要以什么开始/结尾,大小写敏感
istartswith和iendswith: 要以什么开始/结尾,大小写不敏感

跨关系查询

联合查询(JOIN):

Entry和Blog两个表中有互相关联的name列,如果要联合查询,相当于SQL中的JOIN,则:
Entry.objects.filter(blog__name='Beatles Blog')

三表联合:

Blog.objects.filter(entry_authors_name='lennon')

多条件同时满足(and):

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

多条件只需满足一个(or):

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
F表达式

F表达式用于将模型一个字段与同一个模型另一个字段进行比较

查找comments数目多于pingbacks数目的行
Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

注意这里的大于并非用>表示,而是双下划线+gt
同理,小于是双下划线+lt

pk

pk是primary key缩写,表示主键,相当于一个预设的值

Blog主键是id,则
Blog.objects.get(pk=14)就表示:
Blog.objects.get(id=14)
Q查询

用Q封装查询集合可以进行与,并,非操作

Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
表示查询question字段以Who开头,并且pub_date日期是(2005, 5, 2)或者是(2005, 5, 6)的集合
比较,删除,更新,复制操作

比较:==
删除:delete()方法

>>> Entry.objects.filter(pub_date__year=2005).delete()

更新:update()方法

>>> b = Blog.objects.get(pk=1)
# 修改所有的Entry,让他们都属于b
>>> Entry.objects.all().update(blog=b)

复制:将原实例pk设为None,会创建一个新的实例copy

blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1
#
blog.pk = None
blog.save() # blog.pk == 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值