我爱编程

Django之模型(二)

2018-04-08  本文已影响0人  Python野路子

模型元选项

  1. 每个model都可以定义一个Meta类,使用内部的class Meta 定义模型的元数据,这个类中可以定义一些关于你的配置,Meta是一个model内部的类
  2. 模型元数据是“任何不是字段的数据”,比如排序选项(ordering),数据库表名(db_table)或者人类可读的单复数名称(verbose_name 和verbose_name_plural)。在模型中添加class Meta是完全可选的,所有选项都不是必须的。
class Meta:
        db_table = "topic"
        managed = True
        ordering = ['-id']
        verbose_name = u"主题"
        verbose_name_plural = u"主题列表"

db_table:string,在数据库中的表名,否则Django自动生成为app名字_类名
managed: bool, 默认值为True,这意味着Django可以使用syncdb和reset命令来创建或移除对应的数据库。
ordering: 数组, 默认排序规则,每个字符串是一个字段名,前面带有可选的“-”前缀表示倒序。前面没有“-”的字段表示正序。使用"?"来表示随机排序。
verbose_name: string model对象的描述
verbose_name_plural: string 复数时的描述

模型字段 image.png

模型字段常用的参数 image.png

null与blank:

总之:
blank,只是在form表单验证时可以为空,而在数据库上存储的是一个空字符串;null是在数据库上表现NULL,而不是一个空字符串;
需要注意的是,日期型(DateField、TimeField、DateTimeField)和数字型(IntegerField、DecimalField、FloatField)不能接受空字符串,如要想要在填写表单的时候这两种类型的字段为空的话,则需要同时设置null=True、blank=True;

auto_now 与auto_now_add区别:
auto_now_add: 只有第一次才会生效,比如可以用于文章创建时间
auto_now: 每一次修改保存对象时都会将当前时间更新进去,只有调用Model.save()时更新,在以其他方式(例如 QuerySet.update())更新其他字段时,不会更新该字段,但您可以在此类更新中为字段指定自定义值。可用于文章修改时间;

模型中的关系

一对一:一本书籍有一个编号;
多对一:一本书籍有多个评论;--注意Django只有多对一关系,站在多的角度去看待;
多对多:一本书籍有多个作者,一个作者可以写多本书籍;

class Author(models.Model):
    name = models.CharField(u'姓名', max_length=200)
    email = models.EmailField(u'邮箱')
class Number(models.Model):
    number = models.CharField(u'编号', max_length=200)
class Book(models.Model):
    headline = models.CharField(u'大标题', max_length=255)
    pub_date = models.DateTimeField(u'出版时间')
    authors = models.ManyToManyField(Author)
    number = models.OneToOneField(Number)
class Reply(models.Model):
    book = models.ForeignKey(Book) #外键字段
    content = models.CharField(u'内容', max_length=255)

持久操作

Model.save()
这个方法可以用来插入一条新的数据,也可以用来更新一条数据。如果这个数据在之前数据库中存在了,就只是调用sql的update语句。如果这条数据是新的,就会调用sql的insert语句。示例代码如下:

class UpdateArticle(View):
    def get(self,request):
        # 批量修改
        # UPDATE hello_article SET status=3 WHERE status=2
        # Article.objects.filter(status=2).update(status=3)

        # 单个修改
        # 实际上save方法如果当前实例已经存在于数据库中,它就会当作一个update操作
        # Article.objects.filter(id=7).update(status=4)
        article = Article.objects.get(pk=8) #取出pk=7的对象,然后修改其状态,再保存
        article.status = 0
        article.save()

        #更新之后在查询
        articleAll = Article.objects.all()
        return render(request, 'displayArticle.html', locals())

注意:save操作不止是更新修改的字段,而是会将所有的字段全部更新一遍,不管有没有修改。当你的所有操作都是串行,没有什么并发同时操作同一个model的时候,这样的处理方式,一般不会给你带来任何麻烦。但是并行的时候可能会有影响。
Django后面在save方法里面新增加了一个update_fields参数。这样就可以只修改特定字段了:

user.name = name
user.save(update_fields=['name'])

这样便有效避免了并行save产生的数据冲突。

检索对象

article = Article.objects.get(pk=1) #在django 的ORM查询中,数据库的主键可以用PK代替, 官方推荐使用pk
article = Article.objects.get(id=1)#等同于select * from hello_article where id=1;
articleAll = Article.objects.all()
Article.objects.filter(status = 0)
Article.objects.exclude(status = 0)
#正序:
Book .objects.filter(headline=u'标题').order_by('pub_date')
#倒序,字段前面加-
Book .objects.filter(headline=u'标题').order_by('-pub_date')
#<QuerySet [<Classesgrade: Classesgrade object>, <Classesgrade: Classesgrade object>]>
cgrade =  Classesgrade.objects.all()
#<QuerySet [{'update_time': datetime.datetime(2018, 4, 7, 4, 44, 56, 181307,
 cninfo=<UTC>), 'create_time': datetime.datetime(2018, 4, 7, 4, 44, 56, 181269, 
cninfo=<UTC>), u'number_id': 1L, u'id': 1L, 'name': u'django\u6846\u67b6\u73ed'},
 {'update_time': datetime.datetime(2018, 4, 7, 4, 44, 56, 405850, cninfo=<UTC>), 
'create_time': datetime.datetime(2018, 4, 7, 4, 44, 56, 405816, cninfo=<UTC>), 
u'number_id': 2L, u'id': 2L, 'name': u'django\u6846\u67b6\u73ed'}]>

cgrade.values()
Book .objects.count()
Book .objects.latest('pub_date')
Book .objects.latest('pub_date')
Book .objects.first()
Book .objects.last()
Book .objects.filter(id=1).update(headline="大标题")
Book .objects.filter(id=1).delete()

查找对象的条件

查找对象的条件的意思是传给以上方法的一些参数。比如name__contains=’abc’这个就代表name这个字段包含了abc的意思,相当于是SQL语句中的where语句后面的条件,语法为字段名__规则,以下将对这些规则进行说明:

Book .objects.filter(headline__exact=u'大标题')
或
Book .objects.filter(headline=u'大标题')
Book .objects.filter(headline__iexact=u'大标题')
Book .objects.filter(headline__contains=u'标题')
Book .objects.filter(headline__icontains=u'标题')
Book .objects.filter(id__in=[1, 2, 3])
Book .objects.filter(id__gt=1)
Book .objects.filter(id__gte=1)
Book .objects.filter(id__lt=10)
Book.objects.filter(id__lte=10)
Book .objects.filter(headline__startswith='title')
Book .objects.filter(headline__istartswith='title')
Book .objects.filter(headline__iendswith='le')
Book .objects.filter(headline__iendswith='le')
import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2018, 1, 1)
Book .objects.filter(pub_date__range=(start_date, end_date))
Book .objects.filter(pub_date__isnull=True) zz  ..,. MJ HM 
Book.objects.all()[:2]

*ps:负值的操作,是无法进行。切片可以用来实现翻页显示内容,比如每一页显示10条内容可以利用切片,第page页

        cnumber = Classesnumber.objects.all() #获取Classesnumber的Queryset集
        cn_counts = cnumber.count() #总记录数
        page_count = 4 #每页显示记录
        #求出分多少页
        for page in range((cn_counts / page_count + cn_counts % page_count)): 
            #利用for遍历出每一页的记录数据
            for pagenum in (cnumber[page*page_count:page*page_count + page_count]):
                print(pagenum.classgrade_number)

外键操作

一对一
book = Book.objects.get(pk=1) #先获取从表的对象,Book为从表
book.number #得到book主键为1的对应Number对象主表
book = Book.objects.get(pk=1)
book.number = number #获取Number主类的对象,再赋给book中的关联属性
book.save()  #再save保存
number = Number.objects.get(pk=1) #Number为主类,Book为从类
number.book     #查询编号对应的书籍
多对一
reply = Reply.objects.get(pk=1) #先获取多类(子表)对象
reply.book   # 字表

可以在从表定义时设置related_name 参数来覆盖foo_set 的名称。通过主表来查询子表信息用到反向查询(返回的是管理器,需要all之类返回QuerySet),

# 本身Number对象是没有book属性,django提供的一个反查机制
# 如果设置related_name, 我们就通过related_name反查
# 如果没有设置, django默认设置的是反查class的小写名字
# related_name 可以当成反查所用的别名
book = Book.objects.get(pk=1)
book.reply_set.all()
#还可以进行查询
book = Book.objects.get(pk=1)
book.reply_set.filter(content__contains=’I love’).all()
# 多对一创建的对象,它是默认没有加载外键的,只有当你引用时,它才会加载
reply = Reply.objects.get(pk=1)  #首先主表要有数据,从表才能与之相对应
reply.book = book   #book是从主类获取的对象,此处省略
reply.save()   #再保存

#  反向操作

多对多
Book .authors 等于同Book .objects.filter(reply_id=Reply.id).all()
book = Book.objects.get(pk=1)
book.authors
book = Book(headline="标题",number=number)
book.save()
book.authors.add(author)
book.authors.add(author1)
book.save()
book.authors.remove(author)
book.save()
处理关联对象方法

add(obj1, obj2, ...) 添加的已经存在数据库的数据

添加一指定的模型对象到关联的对象集中。
d = Department.objects.get(pk=1)
s = Student.objects.get(pk=1)
d.student_set.add(s) # 学院d添加学生s

create(**kwargs) 添加不存在的数据 ,将数据直接存入数据库

创建一个新的对象,将它保存并放在关联的对象集返回新创建的对象。
d.student_set.create(name='小明') # 创建一个叫小明的学生,并将他添加到学院d中

remove(obj1, obj2, ...)
从关联的对象集中删除指定的模型对象。删除的是关系表中的数据

d.student_set.remove(s) # 从学院d中删除学生s

clear() 从关联的对象集中删除所有的对象
d.student_set.clear() # 清除学院d中所有学生

注意对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法

多表查询

跨关联关系的查询
Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动帮你处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段:


image.png

举例:

# 查询学院名字为‘软件’的学生的信息 
Student.objects.filter(department__d_name='软件') 
#这种跨越可以是任意的深度。

#查询学生名字中包含‘xiao’的学生的学院信息
Department.objects.filter(student__s_name__contains='xiao')

# 查询学号为1的学生所有的课程
Course.objects.filter(student__s_id=1)

# 查询报了课程1的所有的学生
Student.objects.filter(course__c_id=1)

# 查询报了'python'课程的的学生的所属学院的信息
Department.objects.filter(student__course__c_name='python') #三个表关联查询
总结:
  1. Object对象获取某一列值(或者说是获取某个属性)的时候,使用点来获取。我们跨表查询时,也是使用点来获取。或者用_set反查询,_set:提供了对象访问相关联表数据的方法。但这种方法只能是相关类访问定义了关系的类(主键类访问外键类)。
  2. QuerySet查询集做跨表查询时,使用双下划线"",:两个下划线可以生成连接查询,查询关联的字段信息,可以跨表关联查询,只要一层接一层,可以从头查到尾。

聚合操作

使用aggregate方法进行数据库的聚合操作, 使用QuerySet.aggregate 代表需要使用聚合操作,它返回的是一个字典:

#查询当前作者的平均年龄
Author.objects.aggregate(Avg("age"))
#取最大年龄的作者
Author.objects.aggregate(Max("age"))
#取最小年龄的作业
Author.objects.aggregate(Max("age"))
#统计有多少个作者
Author.objects.aggregate(Count("id"))
#如果需要去重
Author.objects.aggregate(Count("age", distinct=True))
#获取所有作者的年龄总和

Author.objects.aggregate(Sum("age"))
Author.objects.aggregate(Sum("age"),Min("age"), Max("age"))
Author.objects.aggregate(avg_age=Avg("age"))   >>>{avg_age:平均年龄值}
#统计每本书的作者有多少
Book.objects.annotate(Count("anthors"))

#统计每个年龄分别有多少人
# values 就等同于group by,返回的是一个字典
# values_list 就等同于group by,, 返回的是一个元祖
Author.objects.values("age").annotate(Count("id"))

事务

如果需要支持事务,mysql引擎必须是InnoDB类型。

 from django.db import transaction
# 这个装饰器不能在通用View视图中使用
# 现在django还只提供了在view函数中使用的装饰器
@transaction.atomic
def model_study(request):
    # 使用事务装饰器以后
    # 整个view函数里面的数据库操作
    # 要么全部成功
    # 要么全部失败
    # 下面的代码在一个事务中执行,一但出现异常,整个函数中所有的数据库操作全部都会回滚
    book = Book.objects.create(headline="事务操作1")
    author = Author.objects.create(name="kevin", email="test@qq.com", age=28)
    book.authors.add(author)
    book.save()
    # assert not book.headline.find("操作") >= 0, "这是敏感关键字"
    return render(request, "model_study/model_study.html")
from django.db import transaction
class ViewClass(View)
    def get(self, request)
        # 下面的代码在自动提交模式下执行(Django的默认模式)
        with transaction.atomic():   # with中的代码,全部都会保持原子性     
            # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
            book = Book.objects.create(headline="事务操作3")
            author = Author.objects.create(name="kevin", email="test@qq.com", age=28)
            book.authors.add(author)
            book.save()
            assert 1==1
            # raise Exception, "这里出现了一个bug"

ps: with 内部最好不要使用try...catch...模块,否则可能会影响django的事务异常判断。

课后练习

1、创建一个班级的模型(名称、班号(一对一外键),创建时间(自动添加),修改时间(自动更新))
2、创建一个班号的模型(号码)
3、创建一个学生的模型(名称、班级(多对一外键 ),老师(多对多),年龄,性别)
4、创建一个老师的模型( 名称,年龄,性别,班级(多对一外键))

#班号模型
class Classesnumber(models.Model): #类名代表了数据库表名,且继承了models.Model,类里面的字段代表数据表中的字段(name)
    # 属性=models.字段类型(选项)
    # 如果没有添加主键,django会默认添加一个ID的主键
    classgrade_number = models.CharField(u'号码',max_length=20) #备注也可用verbose_name
    class Meta: #模型元选项
        db_table = u'classnumber'   #在数据库中的表名,否则Django自动生成为app名字_类名
        managed = True
        # 数据的默认排序, 如果需要倒序,则添加"-"号即可,这里可以按多个排序
        # 多个排序会按你的数组列表顺序进行排序
        ordering = ['id','classgrade_number']
        # 描述,当查询结果是一条记录时,它的描叙
        verbose_name = u'班号' #对象的描述
        # 如果查询结果为多个记录,则返回verbose_name_plural的描叙
        verbose_name_plural = u'班号集' #复数时的描述
#班级模型
class Classesgrade(models.Model):
    name = models.CharField(u'名称',max_length=20)
    create_time = models.DateTimeField(u'创建时间',auto_now_add=True)  #auto_now_add只有第一次才会生效
    update_time = models.DateTimeField(verbose_name= u'修改时间',auto_now=True)#auto_now每一次修改的动作,都会更新一个时间
    #与班级一对一关系,关联属性,Django会自动建立个属性_id字段
    number = models.OneToOneField(Classesnumber)
    class Meta:
        db_table = 'classesgrade'
        managed = True
#老师模型
class Teacher(models.Model):
    name = models.CharField(u'姓名',max_length=20)
    age = models.IntegerField(u'年龄')
    sex = models.CharField(u'性别',max_length=2)
    #老师与班级多对一,关联属性在多方定义
    #db_constraint:bool  是否建立外键约束,
    #to_field:string 关联到的关联对象的字段名称。默认地,Django 使用关联对象的主键。
    #CASCADE:级联删除,如果删除,相关联的那个也会删除
    classesno = models.ForeignKey(Classesgrade,db_constraint = True,to_field='id',on_delete = models.CASCADE)
    class Meta:
        db_table = 'teacher'
        managed = True
#学生
class Student(models.Model):
    name = models.CharField(u'姓名',max_length=20)
    age = models.IntegerField(u'年龄')
    sex = models.CharField(u'性别',max_length=2)
    classesno = models.ForeignKey(Classesgrade,db_constraint = True,to_field='id',on_delete = models.CASCADE)
    # 多对多,Django会自动创建中间表
    teacher = models.ManyToManyField(Teacher,related_name = 'teacher_set')
    class Meta:
        db_table = 'student'
        managed = True
class AddInfor(View):
    def get(self,request):
        #添加班号数据
        #可以用save和create方式
        cnumber1 = Classesnumber.objects.create(classgrade_number = '001')
        cnumber2 = Classesnumber.objects.create(classgrade_number = '002')

        #添加班级数据:
        #如果存在外键关联,主表必须首先得先有数据,一对一关系的添加数据
        #一对一赋值必须保持一个对象只对应一个外键
        cnumber3 = Classesnumber.objects.get(pk=1)  #1对1,先取出主表的pk=1对象
        Classesgrade.objects.create(name = u'django框架班',number = cnumber3 ) #再赋给外键
        cnumber4 = Classesnumber.objects.get(pk=2)
        cgrade = Classesgrade(name = u'django框架班',number = cnumber4)
        cgrade.save()

        # 添加老师数据:
        #获取班级对象
        cgrade1 = Classesgrade.objects.get(pk=1)  #1对多,先取出主表的pk=1对象
        cgrade2 = Classesgrade.objects.get(pk=2)  #1对多,先取出主表的pk=2对象

        # # 通过获取一端对象,则这里要用类属性而不是表字段的名字
        Teacher.objects.create(name = u'k',age = 28,sex = u'男',classesno = cgrade1)
        Teacher.objects.create(name = u'山',age = 28,sex = u'男',classesno = cgrade1)
        Teacher(name = u'不',age = 28,sex = u'男',classesno = cgrade2).save()

        #添加学生数据views.py中:
        #与班级,多对一外键
        stu1 = Student()
        stu1.name = u'学生1'
        stu1.age = 20
        stu1.sex = u'男'
        stu1.classesno = cgrade1
        stu1.save()

        stu2 = Student(name = u'学生2',age = 22,sex = u'女',classesno = cgrade2)
        stu2.save()
        stu3 = Student.objects.create(name = u'学生3',age = 21,sex = u'男',classesno = cgrade1)
        #与老师多对多
        #多对多的添加,需要使用add方法
        #多对多的添加,必须主类必须在数据库已经存在
        tch1 = Teacher.objects.get(name__exact= u'k')
        tch2 = Teacher.objects.get(name__exact= u'山')
        tch3 = Teacher.objects.get(name__exact= u'不')

        stu1.teacher.add(tch1)
        stu1.teacher.add(tch2)
        stu1.save()

        stu2.teacher.add(tch2,tch3)
        stu2.save()

        stu3.teacher.add(tch1,tch3)
        stu3.save()
        return render(request,'result.html',locals())
#app应用urls.py中
urlpatterns = [
    url(r'^register/$', views.Register.as_view(),name='register'),
    url(r'^login/$', views.Login.as_view(),name = 'login'),
    url(r'^index/$', views.Index.as_view(),name='index'),
    url(r'^logout/$', views.Logout.as_view(),name='logout')
]
class QueryInfor(View):
    def get(self,request):
        #查询性别为男的学生
        stu_boys = Student.objects.filter(sex__exact = u'男')
        #查询年龄大于20岁的学生
        stu_20 = Student.objects.filter(age__gt = 20)
        #获取所有学生、并按年龄排序
        stu_all = Student.objects.all().order_by('age')
        #获取所有学生并排除性别为女的学生
        stu_nogirls = Student.objects.exclude(sex = u'女')
        #获取学生总数
        stu_sum = Student.objects.count()
        #获取最后创建的班级
        last_grade = Classesgrade.objects.latest('create_time')

        cgrade1 = Classesgrade.objects.get(pk = 1)
        cgrade2 = Classesgrade.objects.get(pk = 2)

        #查询班级下老师
        #本身班级对象是没有老师属性,django提供的一个反查机制
        # 如果设置related_name, 我们就通过related_name反查
        # 如果没有设置, django默认设置的是反查class的小写名字
        # related_name 可以当成反查所用的别名
        tchs1 = cgrade1.teacher_set.all() #xxx_set 实际返回的是一个空值,如需访问它们,则要进行一个查询QuerySet操作
        tchs2 = cgrade2.teacher_set.all()

        #查询班级下学生
        stu1 = cgrade1.student_set.all()
        stu2 = cgrade2.student_set.all()

        #查询一个班级的编号,1对1 反查
        cgradeno1 =cgrade1.number #cgrade1.number是个<Classesnumber: Classesnumber object>

        cgradeno2 = cgrade2.number

        #查询年龄最大的学生
        sage = Student.objects.aggregate(max_age = Max('age')) #以字典形式返回年龄最大值,{'age__max': 22}
        maxage_stu = Student.objects.filter(age = sage['max_age'])
        #filter(**kwargs)方法:根据参数提供的提取条件,获取一个过滤后的QuerySet。所以在前端不能直接获取对象的方式来,需要遍历来获取,即使只有一个;

        #查询年龄最小的学生
        sage = Student.objects.aggregate(Min('age')) #以字典形式返回年龄最大值,{'age__max': 22}
        minage_stu = Student.objects.filter(age = sage[sage.keys()[0]]) #sage.keys()[0]获取字典的键

        #avgage_stu查询学生的平均年龄
        sage = Student.objects.aggregate(Avg('age'))
        
        for key,value in sage.items():
            keys = key
            age = value

        #查询每个年龄的学生数量,按年龄进行分组,然后统计数量select age,count(age) from student group by age;
        agestucount = Student.objects.values('age').annotate(Count('id')) #annotate返回的是一个QuerySet,可以继续进行查询
        return render(request,'queryInfor.html',locals())

页面效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>查询信息</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>

<h2>1.查询性别为男的学生:</h2>
<p>
{%for stu_boy in stu_boys%}
姓名:{{stu_boy.name}}<br/>
性别:{{stu_boy.sex}}<br/>
年龄:{{stu_boy.age}}<br/>
班级:{{stu_boy.classesno_id}}<br/>
{%endfor%}
</p>
<hr/>

<h2>2.查询年龄大于20岁的学生:</h2>
<p>
{%for stu in stu_20%}
姓名:{{stu.name}}<br/>
性别:{{stu.sex}}<br/>
年龄:{{stu.age}}<br/>
班级:{{stu.classesno_id}}<br/>
{%endfor%}
</p>
<hr/>

<h2>3.获取所有学生、并按年龄排序:</h2>
<p>
{%for stu in stu_all%}
姓名:{{stu.name}}<br/>
性别:{{stu.sex}}<br/>
年龄:{{stu.age}}<br/>
班级:{{stu.classesno_id}}<br/>
{%endfor%}
</p>
<hr/>

<h2>4.获取所有学生并排除性别为女的学生:</h2>
<p>
{%for stu in stu_nogirls%}
姓名:{{stu.name}}<br/>
性别:{{stu.sex}}<br/>
年龄:{{stu.age}}<br/>
班级:{{stu.classesno_id}}<br/>
{%endfor%}
</p>
<hr/>

<h2>5.获取学生总数:</h2>
<p>
    {{stu_sum}}
</p>
<hr/>

<h2>6.获取最后创建的班级:</h2>
<p>
名称:{{last_grade.name}}<br/>
创建时间:{{last_grade.create_time}}<br/>
更新时间:{{last_grade.update_time}}<br/>
对应班号:{{last_grade.number_id}}
</p>
<hr/>

<h2>11.查询一个班级下有那些老师:</h2>
<p>
{{cgrade1.name}}第{{cgrade1.number.id}}个班老师:<br/>
{%for tch in tchs1%}
姓名:{{tch.name}}<br/>
性别:{{tch.sex}}<br/>
年龄:{{tch.age}}<br/>
班级:{{tch.classesno_id}}<br/> <!--tch.classesno 对象.类属性形式不行,因为还是一个对象,要么用对象.表字段名,要么对象.类属性.主表主键 -->
{%endfor%}
<hr/>
{{cgrade2.name}}第{{cgrade2.number_id}}个班老师:<br/>
{%for tch in tchs2%}
姓名:{{tch.name}}<br/>
性别:{{tch.sex}}<br/>
年龄:{{tch.age}}<br/>
班级:{{tch.classesno.id}}<br/>
{%endfor%}
</p>
<h2>22.查询一个班级下有那些学生:</h2>
<p>
{{cgrade1.name}}第{{cgrade1.number.id}}个班学生:<br/>
{%for stu in stu1%}
姓名:{{stu.name}}<br/>
性别:{{stu.sex}}<br/>
年龄:{{stu.age}}<br/>
班级:{{stu.classesno_id}}<br/>
{%endfor%}
<hr/>
{{cgrade2.name}}第{{cgrade2.number_id}}个班学生:<br/>
{%for stu in stu2%}
姓名:{{stu.name}}<br/>
性别:{{stu.sex}}<br/>
年龄:{{stu.age}}<br/>
班级:{{stu.classesno_id}}<br/>
{%endfor%}
</p>
<h2>33.查询一个班级的编号:</h2>
<p>
第{{cgrade1.number_id}}个班编号:{{cgradeno1.classgrade_number}}<br/>
第{{cgrade2.number_id}}个班编号:{{cgrade2.number.classgrade_number}}
</p>
<h2>44、查询年纪最大的学生</h2>
<p>
{% for stu in maxage_stu %}
姓名:{{stu.name}}<br/>
性别:{{stu.sex}}<br/>
年龄:{{stu.age}}<br/>
班级:{{stu.classesno_id}}<br/>
{% endfor %}
</p>
<h2>55、查询年纪最小的学生</h2>
<p>
{% for stu in minage_stu %}
姓名:{{stu.name}}<br/>
性别:{{stu.sex}}<br/>
年龄:{{stu.age}}<br/>
班级:{{stu.classesno_id}}<br/>
{% endfor %}
</p>
<h2>66、查询学生的平均年龄</h2>
<p>
平均{{keys}}:{{value}}z
</p>
<h2>77、查询每个年龄的学生数量</h2>
{% for dic in agestucount%} <!--agestucount是一个QuerySet,需要从中迭代出来 -->
    {% for age,countstu in dic.items %} <!--再将每一个遍历出来的字典通过items将键值取出来 -->
        {{age}}:{{countstu}}
    {% endfor %}
    ;<br/>
{% endfor %}
</body>
</html>
上一篇下一篇

猜你喜欢

热点阅读