Django ORM模型操作

Django连接MySQL

使用Django来操作MySQL,需要安装一个驱动程序。驱动程序有多重选择。比如pymysql以及mysqlclient,这里我们使用mysqlclientmysqlclient安装非常简单

pip install mysqlclient

Django配置连接数据库,配置项目的 settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'devops',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'OPTIONS': {
            'init_command': 'SET default_storage_engine=INNODB;',
        },
    }
}
settings.py

 

创建ORM模型

ORM模型一般都是放在appmodels.py文件中,每个app都可以拥有自己的模型。并且为这个模型要映射到数据库中,那么这个app必须放在settings.pyINSTALL_APP中。 创建在app01中创建模型如下

from django.db import models


class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    pub_date = models.DateField()
    publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
    authors = models.ManyToManyField("Author")
    create_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)


class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=64)
    email = models.EmailField()
    create_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)


class Author(models.Model):
    gender_choices = (
        (0, ""),
        (1, ""),
        (2, "保密")
    )
    name = models.CharField(max_length=32)
    gender = models.SmallIntegerField(choices=gender_choices)
    addr = models.CharField(max_length=64)
    age = models.SmallIntegerField()
    birthday = models.DateField()
    create_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)
app01.models.py

在Django中,如果一个模型没有定义主键,那么会自动生成一个自动增长的int类型的主键,并且这个主键的名字叫做id

映射模型到数据库中

  1. 在命令行中终端执行 python manage.py makemigrations <app_name>来生成迁移脚本,不指定app,则是所有的app
  2. 同样在命令行中,执行命令python manage.py migrate来将迁移脚本映射到数据库中
python manage.py makemigrations app01
python manage.py migrate

 

模型常用字段

CharField

在数据库层面是varchar类型,在使用的时候必须要指定最大的长度参数(max_length)

nick_name = models.CharField(max_length=50, verbose_name='昵称', default='')

IntegerField

整形。值的区间是-2147483648——2147483647

click_nums = models.IntegerField(default=0, verbose_name='点击数')

FloatField

浮点类型。映射到数据库中是float类型, 必须提供两个参数, max_digits(总位数,不包括小数点和符号), decimal_places(小数位数)

price = modes.FloatField(max_digits=5, decimal_places=2, verbose_name='价格')  

BooleanField

在模型层面接收的是True/False。在数据库层面是tinyint类型。如果没有指定默认值,默认值是None

has_read = models.BooleanField(default=False, verbose_name='是否已读')

TextField

大量的文本类型。映射到数据库中是longtext类型

details = models.TextField(verbose_name='课程详情')

UUIDfield

只能存储uuid格式的字符串。uuid是一个32位的全球唯一的字符串,一般用来作为主键

import uuid

id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

DateField

日期类型

birthday = models.DateField(verbose_name='生日')

DateTimeField

日期时间类型

auto_now 当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳
auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.

add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')

EmailFiled

一个带有检查Email合法性的 CharField,不接受 maxlength 参数

email = models.EmailField(verbose_name='邮箱')

URLField

类似于CharField,只不过只能用来存储url格式的字符串。并且默认的max_length是200

url = models.URLField(max_length=200, verbose_name='访问地址')

 

字段常用参数

verbose_name

一个详细的名称。如果没有给出详细名称,Django将使用字段的属性名称自动创建它

city = models.ForeignKey(CityDict, verbose_name='所在城市')

null

如果为True,Django将NULL在数据库中存储空值。默认是False, 避免在字符串的类型字段上使用,例如CharFiled和TextField

对于基于字符串和非基于字符串的字段,您还需要设置blank=True是否允许在表单中允许空值,因为该 null参数仅影响数据库存储

blank

标识这个字段在表单验证的时候是否可以为空。默认是False。 这个和null是有区别的,null是一个纯数据库级别的。而blank是表单验证级别的

default

默认值。可以为一个值,或者是一个函数,但是不支持lambda表达式。并且不支持列表/字典/集合等可变的数据结构

primary_key

是否为主键。默认是False

unique

在表中这个字段的值是否唯一。一般是设置手机号码/邮箱等

choices

用作此字段的选项

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)


>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
示例

 

模型中的Meta配置

对于一些模型级别的配置。我们可以在模型中定义一个类,叫做Meta。然后在这个类中添加一些类属性来控制模型的作用。比如我们想要在数据库映射的时候使用自己指定的表名,而不是使用模型的名称。那么我们可以在Meta类中添加一个db_table的属性。示例代码如下:

class Book(models.Model):
    name = models.CharField(max_length=20,null=False)
    desc = models.CharField(max_length=100)

    class Meta:
        db_table = 'book_model'
db_table

如果没有指定db_table参数,那么在映射的时候将会使用(app名_模型名)来作为默认的表名

 ordering

设置在提取数据的排序方式。比如我想在查找数据的时候根据添加的时间排序,那么示例代码如下:

class Book(models.Model):
    name = models.CharField(max_length=20,null=False)
    desc = models.CharField(max_length=100)
    pub_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['pub_date']
ordering

verbose_name

verbose_name: 对象的可读名称,单数 verbose_name_plural: 对象的可读名称,复数, 如果没有给出,Django将使用verbose_name+ "s"

class CityDict(models.Model):
    name = models.CharField(max_length=20, verbose_name='城市名')
    desc = models.CharField(max_length=200, verbose_name='描述')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
 
    class Meta:
        verbose_name = '城市'
        verbose_name_plural = verbose_name
verbose_name

 

基本操作 (基于上面创建的模型进行操作)

前面我们创建给4给模型

  • Book(图书)
  • Publish(出版社)
  • Author(作者)

首先给这些表插入一些测试数据

def ormDemo(request):
    if request.method == "GET":
        # 增加出版社
        # Publish.objects.create(name="华山出版社", city="华山", email="hs@163.com")
        # Publish.objects.create(name="明教出版社", city="黑木崖", email="mj@163.com")

        # 增加作者
        # Author.objects.create(name="令狐冲", gender=1, addr="华山", age=25, birthday="1994-5-23")
        # Author.objects.create(name="任我行", gender=1, addr="黑木崖", age=58, birthday="1961-8-13")
        # Author.objects.create(name="任盈盈", gender=0, addr="黑木崖", age=23, birthday="1996-5-20")

        # 增加图书

        huasan_publish = Publish.objects.filter(name="华山出版社").first()
        mingjiao_publish = Publish.objects.filter(name="明教出版社").first()
        ling = Author.objects.filter(name="令狐冲").first()
        ying = Author.objects.filter(name="任盈盈").first()
        xing = Author.objects.filter(name="任我行").first()

        Book.objects.create(name="独孤九剑", price=200, pub_date="2019-1-7", publish=huasan_publish)
        Book.objects.create(name="吸星大法", price=180, pub_date="2018-10-2", publish=mingjiao_publish)
        Book.objects.create(name="葵花宝典", price=220, pub_date="2018-11-12", publish=mingjiao_publish)

        book01 = Book.objects.filter(name="独孤九剑").first()
        book01.authors.add(ling, ying)


        book02 = Book.objects.filter(name="吸星大法").first()
        book02.authors.add(xing)

        book03 = Book.objects.filter(name="葵花宝典").first()
        book03.authors.add(xing)
        return HttpResponse("ok")
测试数据

1、查询 "葵花宝典" 的出版社 所在的城市
book = Book.objects.filter(name="葵花宝典").first()
print(book.publish.city)
2、查询明教出版社所有的书籍名
pub_obj = Publish.objects.filter(name="明教出版社").first()
for book in pub_obj .book_set.all(): print(book.name)
3、查询所有住在华山的作者姓名
authors = Author.objects.filter(addr="华山")
for author in authors:
    print(author.name)
4、查出独孤九剑的所有作者和年龄
book = Book.objects.filter(name="独孤九剑").first()
for author in book.authors.all():
    print(author.name, author.age)

 5、查询"任我行"所有的书籍名称 

author = Author.objects.filter(name="任我行").first()
for book in author.book_set.all():
    print(book.name)

基于双下划线跨表查询

# 查询明教出版社出版过的所有书籍和价格
books = Book.objects.filter(publish__name="明教出版社").values("name", "price")
print(books)
<QuerySet [{'name': '吸星大法', 'price': Decimal('180.00')}, {'name': '葵花宝典', 'price': Decimal('220.00')}]>


# 查出"任我行"所有的书籍名字
books = Author.objects.filter(name="任我行").values("book__name")
print(books)
<QuerySet [{'book__name': '吸星大法'}, {'book__name': '葵花宝典'}]>

 

 

 

 

 

 






 

posted @ 2020-11-28 13:08  sellsa  阅读(189)  评论(0编辑  收藏  举报