Django模型基础(ORM、字段类型、字段参数、增删改查和分页)

模型基础:

字段类型:

django根据属性的类型确定以下信息

  • 当前选择的数据库⽀持字段的类型
  • 渲染管理表单时使⽤的默认html控件
  • 在管理站点最低限度的验证
  • django会为表增加⾃动增⻓的主键列,每个模型只能有⼀个主键列,如果使⽤选项设置某属性为主键列后,则django不会再⽣成默认的主键列。

属性命名限制

·遵循标识符规则

·由于django的查询⽅式,不允许使⽤连续的下划线

定义属性时,需要字段类型,字段类型被定义在django.db.models.fields⽬录下,为了⽅便使⽤,被导⼊到django.db.models中

使⽤⽅式

  • 导⼊from django.db import models
  • 通过models.Field创建字段类型的对象,赋值给属性

逻辑删除和物理删除

​ 对于重要数据都做逻辑删除,不做物理删除,实现⽅法是定义is_delete属性,类型为BooleanField,默认值为False。(物理删除就是真正对数据库进行操作,逻辑删除就是打标记,筛选一下就可以)。

is_delete = models.BooleanField(default=False)

常⽤字段类型:

  • AutoField

    ·⼀个根据实际ID⾃动增⻓的IntegerField,通常不指定, 如果不指定,主键字段id将⾃动添加到模型中。

  • CharField(max_length=字符⻓度)

    ·字符串,默认的表单样式是 Input,相当于数据库中的varchar.

  • TextField

    ·⼤⽂本字段,⼀般超过4000使⽤,默认的表单控件是Textarea,相当于数据库中的text.

  • IntegerField

    ·整数

  • DecimalField(max_digits=None, decimal_places=None)

    ·使⽤python的Decimal实例表示的⼗进制浮点数

    ·参数说明

    ·DecimalField.max_digits

    ·位数总数

    ·DecimalField.decimal_places

    ·⼩数点后的数字位数

  • FloatField

​ ⽤Python的float实例来表示的浮点数

  • BooleanField

​ True/False 字段,此字段的默认表单控制是CheckboxInput

  • DateField([auto_now=False, auto_now_add=False])

​ ·使⽤Python的datetime.date实例表示的⽇期

​ ·参数说明

​ ·DateField.auto_now

​ 每次保存对象时,⾃动设置该字段为当前时间,⽤于"最后⼀次修改"的时间戳,它总是使⽤当前⽇期,默认为false。

DateField.auto_now_add

当对象第⼀次被创建时⾃动设置当前时间,⽤于创建的时间戳,它总是使⽤创建时的⽇期,默认为false。

​ 注意:auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发⽣错误的结果

  • TimeField

​ 使⽤Python的datetime.time实例表示的时间,参数同DateField。

  • DateTimeField

·使⽤Python的datetime.datetime实例表示的⽇期和时间,参数同DateField。

  • FileField

    ⼀个上传⽂件的字段

  • ImageField

继承了FileField的所有属性和⽅法,但对上传的对象进⾏校验,确保它是个有效的image

需要安装Pillow: "pip install Pillow"

字段参数:

字段参数写在models.BooleanField()内部。

# 常⽤字段选项(通过字段选项,可以实现对字段的约束):
1、 null=True
数据库中字段是否可以为空
2、 blank=True
django的 Admin 中添加数据时是否可允许空值

⼀般null=True & blank=True 搭配着⽤,出现null=True就⽤上blank=True
3、 primary_key = True
主键,对AutoField设置主键后,就会代替原来的⾃增 id 列
4、 auto_now 和 auto_now_add
auto_now	⾃动创建---⽆论添加或修改,都是当前操作的时间
auto_now_add ⾃动创建---永远是创建时的时间

5、 choices (后台admin下拉菜单)
//限制选择
USER_TYPE_LIST = (
(1, '超级⽤户'),
(2, '普通⽤户'),)

user_type = models.IntegerField(choices=USER_TYPE_LIST,
default=1, verbose_name='⽤户类型')
6、 max_length 最⼤⻓度
7、 default	默认值
8、 verbose_name	Admin(后台显示的名称)中字段的显示名称(类似注释)
9、 name|db_column		数据库中的字段名称
10、unique=True	不允许重复
11、db_index = True	数据库索引,例如:如果你想通过name查询的更快的话,给他设置为索引即可
12、editable=True 在Admin⾥是否可编辑,不可编辑则不显示
13、设置表名
class Meta:
	db_table = 'person' (表名)

案例实战:

创建项目工程:

数据迁移:

python manage.py makemigrations

映射数据库:

python manage.py migrate

注意:每对模型进行一次修改,都需要重新进行映射。

对于新添加的列,最后给一个默认值,因为可能前几列的值已经固定了,但是我们后面的列没有进行赋值,就会存在问题.

后台管理配置:

设置管理员:

python manage.py createsuperuser

后台查看:

显示问题:

如果想让其显示除需要定义model的魔术方法例如:

py 复制代码
    def __str__(self): # 控制
        return f'{self.id}-{self.name}-{self.age}'

    def __repr__(self):
        return f'{self.id}-{self.name}-{self.age}'

如何实现回滚操作呢?

1.首先删除migrantions中的内容,如下:

  1. 在数据库中删除

App下的models.py

py 复制代码
from django.db import models


# 模型 字段类型和约束
class UserModel(models.Model):
    # uid 会成为主键,原来的id不会创建
    uid = models.AutoField(auto_created=True, primary_key=True)
    # CharField: 字符串类型,unique唯一,db_index索引
    # 名字唯一
    name = models.CharField(max_length=30, unique=True, db_index=True)
    # IntegerField: 整数类型,default默认值
    age = models.IntegerField(default=18)
    # BooleanField: bool类型
    sex = models.BooleanField(default=True)

    # # TextField:长字符串,大文本,
    #       null=True 表示可以为空,blank=True在Admin管理页面可以为空,一般都是同时写
    info = models.TextField(null=True, blank=True)
    # # FloatField: 小数
    salary = models.FloatField(default=100000.345)

    # DecimalField: 十进制小数,
    #     max_digits=4:最大长度
    #     decimal_places=2:小数点后是2位
    money = models.DecimalField(max_digits=4, decimal_places=2, default=10.34)

    # # 日期
    birthday = models.DateField(default='2000-03-04')

    birthday2 = models.DateTimeField(auto_now=True)  # 每一次修改后都会自动修改该时间为最新的修改时间
    birthday3 = models.DateTimeField(auto_now_add=True)  # 第一次添加数据的时候的时间,以后不会再修改
    birthday4 = models.DateTimeField(auto_now_add=True)  # 第一次添加数据的时候的时间,以后不会再修改

    # # 文件和图片
    # 保存图片的二进制  可以为空
    icon = models.FileField(null=True, blank=True, upload_to='static/uploads')
    icon2 = models.ImageField(null=True, blank=True, upload_to='static/uploads')

    #
    # # 其他约束
    # 元组中第一个参数是我们输入的元素
    # name 属性表示在数据库中生成的字段名字
    # db_column 数据库中的字段名称
    # verbose_name 是在后台管理系统中显示出来的名字
    # editable=True 在Admin⾥是否可编辑,不可编辑则不显示
    choices = ((1, '青铜'), (2, '大师'), (3, '王者'))
    user_type = models.IntegerField(choices=choices, default=1,
                                    name='utype', verbose_name='用户类型')
    user_type2 = models.IntegerField(default=1,  editable=False,
                                     db_column='utype2', verbose_name='用户类型2')

    def __str__(self):
        return f'{self.name} - {self.age}'

模型操作:

⼀般的数据库操作流程:

  1. 创建数据库,设计表结构和字段
  2. 连接Mysql数据库,并编写数据访问层代码
  3. 业务逻辑层去调⽤数据访问层执⾏数据库操作

​ Django通过Model操作数据库,不管你数据库的类型是MySql或者Sqlite,Django⾃动帮你⽣成相应数据库类型的SQL语句,所以不需要关注SQL语句和类型,对数据的操作Django帮我们⾃动完成。只要会写Model就可以了。

​ django使⽤对象关系映射(Object Relational Mapping,简称ORM)框架去操控数据库。

​ ORM(Object Relational Mapping)对象关系映射,是⼀种程序技术,⽤于实现⾯向对象编程语⾔⾥不同类型系统的数据之间的转换。

ORM:

模型 <=>
类结构 -> 表结构
对象 -> 表的⼀条数据
类属性 -> 表的字段

增删改查:

添加:
# models基本操作
# 增:
1)创建对象实例,然后调⽤save⽅法:
    obj = Author()
    obj.first_name = 'zhang'
    obj.last_name = 'san'
    obj.save()      
2)创建对象并初始化,再调⽤save⽅法:
	obj = Author(first_name='zhang', last_name='san') obj.save()
3)使⽤create⽅法
	Author.objects.create(first_name='li', last_name='si') 
4)使⽤get_or_create⽅法,可以防⽌重复
	Author.objects.get_or_create(first_name='zhang', last_name='san')
py 复制代码
class PersonModel(models.Model):
    name = models.CharField(max_length=30, unique=True)
    age = models.IntegerField(default=18)

    class Meta:
        # 自定义表名(默认是app的名字+模型名的小写)
        db_table = 'tb_person'

    def __str__(self):
        return f'{self.id}-{self.name}-{self.age}'

    def __repr__(self):
        return f'{self.id}-{self.name}-{self.age}'

迁移:

查看表结构:

App下的views.py 提供接口

py 复制代码
import math

from django.db.models import Max, Min, Sum, Avg, Count
from django.shortcuts import render, HttpResponse

# 导入models
from App.models import *


# 增加数据
def add_person(request):
    # 方式1
    # try:
    #     p = PersonModel()
    #     p.name = '李四'
    #     p.age = 44
    #     p.save()  # 同步到数据库表中
    # except Exception as e:
    #     return HttpResponse('添加失败')
    #
    # return HttpResponse('添加成功!')

    # 方式2
    # try:
    #     p = PersonModel(name='王五', age=55)
    #     p.save()  # 同步到数据库表中
    # except Exception as e:
    #     return HttpResponse('添加失败')
    #
    # return HttpResponse('添加成功!')

    # 方式3
    # try:
    #     PersonModel.objects.create(name='赵六', age=66)
    # except Exception as e:
    #     return HttpResponse('添加失败')
    #
    # return HttpResponse('添加成功!')

    # 方式4
    # try:
    #     ret = PersonModel.objects.get_or_create(name='钱七', age=77)
    #     print('ret:', ret)
    #     # ret: (<PersonModel: PersonModel object (5)>, True)
    #     # 如果是第一次创建:则是True,如果已经存在则是False
    #
    # except Exception as e:
    #     return HttpResponse('添加失败')



    # 添加多条数据
    for i in range(21, 51):
        PersonModel.objects.create(name=f'武{i}范', age=i)

    return HttpResponse('添加成功!')

项目工程下的urls.py 写路由

py 复制代码
from django.contrib import admin
from django.urls import path

from App.views import *

urlpatterns = [

    path('add/', add_person),  # 添加数据
    # path('del/', del_person),  # 删除数据
    # path('update/', update_person),  # 修改数据
    # path('get/', get_person),  # 查询数据
    #
    # # 分页
    # path('paginate/<int:page>/', paginate, name='paginate'),
    # path('paginate2/<int:page>/', paginate2, name='paginate2'),

    path('admin/', admin.site.urls),
]
删除:
# 删:
	使⽤Queryset的delete⽅法:
# 删除指定条件的数据
    Author.objects.filter(first_name='zhang').delete() # 删除所有数据
    Author.objects.all().delete()
    注意: objects不能直接调⽤delete⽅法。
    使⽤模型对象的delete⽅法:
    obj = Author.objects.get(id=5) obj.delete()

views.py

py 复制代码
# 删除数据
def del_person(request):
    # 删除数据:
    #  1. 先找到要删除的数据
    #  2. 然后删除
    try:
        # 删除一条数据
        # p = PersonModel.objects.first()  # 第一条数据
        # p.delete()

        # 删除多条数据
        PersonModel.objects.filter(age__gt=15).delete()  # age>15的多条数据

    except Exception as e:
        return HttpResponse('删除失败!')

    return HttpResponse('删除成功!')
修改:
# 改:
	Author.objects.filter(last_name='dfdf').update(last_name='san')
模型没有定义update⽅法,直接给字段赋值,并调⽤save,能实现update的功能,⽐如:
	obj = Author.objects.get(id=3) 
	obj.first_name = 'zhang' 
	obj.save()
save更新时会更新所有字段。如果只想更新某个字段,减少数据库操作,可以这么做:
    obj.first_name = 'li'
    obj.save(update_fields=['first_name'])

views.py

py 复制代码
# 修改数据
def update_person(request):
    # 修改数据
    #  1. 先找到要修改的数据
    #  2. 然后修改
    try:
        # 修改一条数据
        p = PersonModel.objects.first()
        p.age = 666
        # p.save()  # 同步到数据库表中
        p.save(update_fields=['age'])  # 指定更新的字段,提高更新效率

        # 修改多条数据
        # PersonModel.objects.all().update(age=100)

    except Exception as e:
        return HttpResponse('修改失败!')

    return HttpResponse('修改成功!')
查询:
# 查:
get():获取单条数据:
	Author.objects.get(id=123)  # 一般对主键或者唯一的
	如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常如果找到多个,会引发模型类.MultipleObjectsReturned 异常
first():返回查询集(QuerySet)中的第⼀个对象   
last():返回查询集中的最后⼀个对象         
count():返回当前查询集中的对象个数         
exists():判断查询集中是否有数据,如果有数据返回True没有反之 
all():获取全部数据集:
	Author.objects.all()
values(): 获取指定列的值,可以传多个参数!返回包含字典的列表(保存了字段名和对应的值)
	Author.objects.all().values('password')
values_list(): 获取指定列的值,可以传多个参数!返回包含元组列表(只保存值)
	Author.objects.all().values_list('password')
py 复制代码
进阶操作:
# 获取个数
Author.objects.filter(name='seven').count()

Author.objects.filter(id gt=1)	# 获取id⼤于1的值
# select * from Author where id > 1

Author.objects.filter(id gte=1)	# 获取id⼤于或等于1的值
# select * from Author where id >= 1

Author.objects.filter(id lt=10)	# 获取id⼩于10的值
# select * from Author where id < 10

Author.objects.filter(id lte=10)	# 获取id⼩于或等于10的值
# select * from Author where id <= 10

Author.objects.filter(id lt=10, id gt=1)	# 获取id⼤于1 且 ⼩于10的值
# select * from Author where id < 10 and id > 1

Author.objects.filter(id in=[11, 22, 33])	# 获取id在11、22、33中的数据
# select * from Author where id in (11,22,33)

# exclude 除了以外,取反
Author.objects.exclude(id in=[11, 22, 33]) # not in # select * from Author where id not in (11,22,33)

Author.objects.filter(name contains="ven") # contains(和数据库中like语法相同) # select * from Author where name like '%ven%'
Author.objects.filter(name icontains="ven") # icontains⼤⼩写不敏感
Author.objects.filter(name regex="^ven") # 正则匹配
Author.objects.filter(name iregex="^ven") # 正则匹配,忽略⼤⼩写
Author.objects.filter(age range=[10, 20])	# 范围bettwen and

# startswith,istartswith, endswith, iendswith:
# 以什么开始,以什么结束,和上⾯⼀样带i的是⼤⼩写不敏感的, 其实不带i的也忽略⼤⼩写

Author.objects.filter(name='seven').order_by('id')	# asc升序 Author.objects.filter(name='seven').order_by('-id')	# desc降序
Author.objects.all()[10:20] # 切⽚,取所有数据的10条到20条,分⻚的时候⽤的到,
# 下标从0开始,不能为负数, 可以实现分⻚

views.py

py 复制代码
# 查询数据
def get_person(request):

    # get(): 得到一个对象(一条数据) 必须获得一条数据
    #        如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常
    # 	     如果找到多个,会引发模型类.MultipleObjectsReturned 异常
    p = PersonModel.objects.get(id=5)
    # p = PersonModel.objects.get(18)  # 不可以这样写,会报错

    # p = PersonModel.objects.get(pk=6)  # pk:primary key
    # p = PersonModel.objects.get(age=100)  # 可以
    # p = PersonModel.objects.get(age=100)  # 不可以,报错,MultipleObjectsReturned
    # # p = PersonModel.objects.get(age=1000)  # 不可以,报错,DoesNotExist
    # print('*' * 30)
    # print(p, type(p))  # PersonModel对象
    # print(p.name, p.age)
    # print('*' * 30)

#     # all(): 获取所有数据
    # <QuerySet [5-武21范-100, 6-武22范-100, 7-武23范-100, 8-武24范-100, 9-武25范-100, 35-de-100]>
    persons = PersonModel.objects.all()
    print(persons, type(persons))
#     # QuerySet 查询集
#     # 可以遍历查询集
    for p in persons:
        print(p.name, p.age)
#
#     # first(): 第一条数据
    p = PersonModel.objects.first()
    print(p.name, p.age)
#
#     # last(): 最后一条数据
    p = PersonModel.objects.last()
    print(p.name, p.age)
    return HttpResponse('查询成功!')

过滤filter:

py 复制代码
#     # filter(): 过滤,使用最多
#     查询有可能一条  也有可能多条,所以得到的是查询集
#     persons = PersonModel.objects.filter()  # 默认没有条件,得到所有数据
    persons = PersonModel.objects.filter(age__gt=300)  # age>300
    persons = PersonModel.objects.filter(age__gte=300)  # age>=300
    persons = PersonModel.objects.filter(age__lt=300)  # age<300
    persons = PersonModel.objects.filter(age__lte=300)  # age<=300
    persons = PersonModel.objects.filter(age=300)  # age=300

#     # 查询集可以做链式调用  相当于子查询
#     print(persons.filter().filter().all().first())
    print(type(persons))  # django.db.models.query.QuerySet
#     for p in persons:
#         print('--- ', p.name, p.age)
# #
#     print(persons.first())
#     print(persons.last())
#     print(persons.exists())  # 查询集是否存在数据,如果存在则为True,否则为False
#     print(persons.count())  # 查询集中的数据个数

    # values() 和 values_list()
    persons = PersonModel.objects.filter().all()
    print("persons:", persons)
    print("list(persons):", list(persons))  # 将查询集强制转换成列表

    # values() : 列表套字典,包括字段和值
    #  <QuerySet [{'name': '武21范', 'age': 100}, {'name': '武22范', 'age': 50}, {'name': '武23范', 'age': 300
    # }, {'name': '武24范', 'age': 100}>
    print("persons.values():", persons.values())  # 列表套字典
    # 指定某个字段
    print("persons.values('name', 'age'):", persons.values('name', 'age'))

    # values_list():  列表套元组, 只有值
    # <QuerySet [(5, '武21范', 100), (6, '武22范', 50), (7, '武23范', 300), (8, '武24范', 100), (9, '武25范', 200), (
    # 35, 'de', 600)]>
    print("persons.values_list():", persons.values_list())
    print("persons.values_list('name', 'age'):", persons.values_list('name', 'age'))
    
    # 包含 正则 in
    print('-' * 60)
    # filter(): 详细, 类似数据库中的where语句
    persons = PersonModel.objects.filter(age__in=[100, 200, 666, 777, 888])  # in
    # exclude(): 排除,取反的意思

    persons = PersonModel.objects.exclude(age__in=[100, 200, 666, 777, 888])  # not in
    persons = PersonModel.objects.filter(age__contains='6')  # 包含, 模糊查找,类似like
    persons = PersonModel.objects.filter(name__contains='3')  # 包含, 模糊查找,类似like
    persons = PersonModel.objects.filter(name__icontains='3')  # 包含, 模糊查找,类似like ignore大小写(忽略大小写)
    persons = PersonModel.objects.filter(name__regex='^wu')  # 正则匹配,姓武的
    persons = PersonModel.objects.filter(name__iregex='^wu')  # 正则匹配,忽略大小写
    persons = PersonModel.objects.filter(age__range=[200, 400])  # 200-400之间,两边都包含

    # 开头和结尾 
    persons = PersonModel.objects.filter(name__startswith='wu')  # 以wu开头,忽略大小写
    persons = PersonModel.objects.filter(name__istartswith='wu')  # 以wu开头,忽略大小写
    persons = PersonModel.objects.filter(name__endswith='wu')  # 以wu结尾,忽略大小写
    persons = PersonModel.objects.filter(name__iendswith='wu')  # 以wu结尾,忽略大小写
    print(persons)

聚合函数:

py 复制代码
#     # 聚合函数:max,min,sum
    # 返回的是字典 {'age__max': 600}
    result = PersonModel.objects.aggregate(Max('age'))  # 最大值  {'age__max': 666}
    result = PersonModel.objects.aggregate(Min('age'))  # 最小值  {'age__min': 100}
    result = PersonModel.objects.aggregate(Sum('age'))  # 求和  {'age__sum': 1666}
    result = PersonModel.objects.aggregate(Avg('age'))  # 平均值  {'age__avg': 333.2}
    result = PersonModel.objects.aggregate(Count('age'))  # 计数  {'age__count': 5}
    print(result)

排序:

py 复制代码
    # 排序
    # 默认是按照升序排列 
    # -字段 表示降序
    persons = PersonModel.objects.all().order_by('age')  # 升序
    persons = PersonModel.objects.all().order_by('age', '-id')  # 先按照age升序,如果age相同则按id降序排列
    persons = PersonModel.objects.all().order_by('-age')  # 降序
    print(persons)
分页:

手动分页:

views.py

py 复制代码
# 分页功能
# 手动分页
def paginate(request, page=1):
    # 页码:page
    # 每页数量:per_page
    per_page = 10

    # 分页功能:
    #  数据 =【1,2,3,4,5,...,100】
    #   第几页       数据范围       数据下标范围      切片
    #   page=1        1 ~ 10      0 ~ 9        [0 : 10]
    #   page=2       11 ~ 20     10 ~ 19       [10 : 20]
    #   page=3       21 ~ 30     20 ~ 29       [20 : 30]
    #   page=4       31 ~ 40     30 ~ 39       [30 : 40]
    #   ...
    #   page=n                        [(n-1) * 10  :  n * 10]
    #   page=page                     [(page-1) * per_page  :  page * per_page]

    # 实现分页功能
    persons = PersonModel.objects.all()
    persons = persons[(page-1) * per_page  :  page * per_page] # 切片

    # 总页数
    total = PersonModel.objects.count()  # 总数据量
    total_page = math.ceil(total / per_page)  # 总页数 向上取整,因为可能有一部分不到10个
    pages = range(1, total_page+1)  # 1,2,3,4,5,6,7...

    data = {'persons': persons,'pages': pages}
    return render(request, 'paginate.html', data)

templates下的paginate.html:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        ul {list-style: none; padding: 0}
        .btns li {
            float: left;
            margin: 5px;
        }
        hr {
            clear: both;
        }
    </style>
</head>
<body>
    <h2>分页功能</h2>
    <hr>

    <ul class="btns">
        {% for page in pages %}
            <li>
                <a href="{% url 'paginate' page %}"> <button>{{ page }}</button> </a>
            </li>
        {% endfor %}


    </ul>

    <hr>
    <ul>
        {% for person in persons %}
            <li>{{ person.name }} - {{ person.age }}</li>
        {% endfor %}
    </ul>


</body>
</html>

当然了,还有进行路由绑定:

自动分页:

py 复制代码
# 分页器:自动分页
from django.core.paginator import Paginator


def paginate2(request, page=1):
    per_page = 10 # 每一页数量

    all_data = PersonModel.objects.all()

    # 分页器
    paginator = Paginator(all_data, per_page)
    persons = paginator.page(page)  # 获取第page页的数据
    pages = paginator.page_range  # 页码范围,可以遍历

    data = {'persons': persons, 'pages': pages}
    return render(request, 'paginate2.html', data)
py 复制代码
from django.contrib import admin
from django.urls import path

from App.views import *

urlpatterns = [

    path('add/', add_person),  # 添加数据
    path('del/', del_person),  # 删除数据
    path('update/', update_person),  # 修改数据
    path('get/', get_person),  # 查询数据
    #
    # 分页
    path('paginate/<int:page>/', paginate, name='paginate'), # 给这个路由函数起一个名字
    path('paginate2/<int:page>/', paginate2, name='paginate2'),

    path('admin/', admin.site.urls),
]

templates下的paginate2.

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        ul {list-style: none; padding: 0}
        .btns li {
            float: left;
            margin: 5px;
        }
        hr {
            clear: both;
        }
    </style>
</head>
<body>
    <h2>分页功能</h2>
    <hr>

    <ul class="btns">

        {% for page in pages %}
            <li>
                <a href="{% url 'paginate2' page %}"> <button>{{ page }}</button> </a>
            </li>
        {% endfor %}

    </ul>

    <hr>
    <ul>
        {% for person in persons %}
            <li>{{ person.name }} - {{ person.age }}</li>
        {% endfor %}
    </ul>


</body>
</html>

总结

本篇博客深入探讨了Django中的模型基础,涵盖了ORM(对象关系映射)的概念及其在Django中的应用,详细介绍了各种字段类型以及常用字段参数的使用方法。通过实战案例的讲解,读者将学习如何在Django中使用模型进行数据操作,并解答了一些常见问题。此外,我们还重点介绍了模型的基本操作,包括CURD(创建、读取、更新和删除)以及分页的实现方法。无论您是初学者还是有一定经验的开发者,本文都将为您提供全面而实用的Django模型知识。

相关推荐
0zxm5 分钟前
06 - Django 视图view
网络·后端·python·django
指尖上跳动的旋律1 小时前
shell脚本定义特殊字符导致执行mysql文件错误的问题
数据库·mysql
ROBOT玲玉1 小时前
Milvus 中,FieldSchema 的 dim 参数和索引参数中的 “nlist“ 的区别
python·机器学习·numpy
一勺菠萝丶1 小时前
MongoDB 常用操作指南(Docker 环境下)
数据库·mongodb·docker
Kai HVZ2 小时前
python爬虫----爬取视频实战
爬虫·python·音视频
古希腊掌管学习的神2 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
m0_748244832 小时前
StarRocks 排查单副本表
大数据·数据库·python
B站计算机毕业设计超人2 小时前
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
大数据·人工智能·爬虫·python·机器学习·课程设计·数据可视化
路人甲ing..2 小时前
jupyter切换内核方法配置问题总结
chrome·python·jupyter
C++忠实粉丝2 小时前
Redis 介绍和安装
数据库·redis·缓存