• <学习笔记>从零开始自学Python-之-web应用框架Django( 十)通用模板


            django相对于flask这种轻框架来说被称为全栈框架,因为它提供了相当多集成好的功能,比如前面讲了模板,其实Django提供了一些通用模板,它们可以让开发人员编写少量代码就能快速实现常见的数据视图。

            有了通用视图,可以把模型作为额外的参数传给 URL 配置。Django 自带的通用视图能实现下述功能:

    • 列出对象并显示单个对象的详细信息。如果创建一个管理学生的应用程序,那么 studentListView 就是学生列表视图。

    • 呈现基于日期的对象,显示为年月日归档页面(带有详细信息),以及“最新”页面。

    • 让用户创建、更新和删除对象——需不需要授权都行。

            这些视图提供了简单易用的接口,在视图中显示数据库里的数据时能为开发者执行多数常见的任务。

    下面介绍Django中常见的几种通用视图。

    1、ListView

            ListView用于展示列表。比如我们现在想用一个页面展示所有学生的列表,我们在原来的views.py里面加入如下代码:

    1. from django.views.generic import ListView
    2. class StudentList(ListView):
    3. template_name = 'student_list.html'
    4. model = Student

    然后新建一个student_list.html文件:

    1. {% extends "base.html" %}
    2. {% block main %}
    3. <h2>学生名单h2>
    4. <ul>
    5. {% for s in student_list %}
    6. <li class="btn">{{ s.name }}, 性别{{s.sex}},年龄{{s.age}},成绩{{s.score}}li>
    7. {% endfor %}
    8. ul>
    9. {% endblock %}

    在url.py文件里设置路由,让视图和模板关联起来

    1. urlpatterns = [
    2. ......
    3. path('students/',StudentList.as_view()),
    4. ]

    然后访问 http://127.0.0.1:8000/students,看到

     2、DetailView

            DetailView用于展示单个模型对象的数据。通常情况下,在URL中向视图提交对象的id,视图使用id获得模型对象,并将模型对象传递给模板。

            我们还是先来扩展DetailView类

    1. class StudentDetail(DetailView):
    2. template_name = 'student_detail.html'
    3. model = Student

    然后新建一个student_detail.html

    1. {% extends "base.html" %}
    2. {% block main %}
    3. <h2>姓名:{{ object.name }}h2>
    4. <p>年龄:{{ object.age }}p>
    5. <p>性别:{{ object.sex }}p>
    6. <p>成绩:{{ object.score }}p>
    7. {% endblock %}

    这里要注意,默认的 object名称是object,如果要自定义名称可以改为:

    1. ......
    2. #指定object名称
    3. template_object_name = 'student'
    4. ......

    最后再设置路由:

    1. urlpatterns = [
    2. ......
    3. path('student//',StudentDetail.as_view()),
    4. ]

    注意这里的  int表示接受的参数为整数,pk表示数据为模型的主键

    然后访问 http://127.0.0.1:8000/student/5/,看到

     如果我们想要增加一些模型里没有的数据,可以通过改写 get_context_data 方法来实现,比如说我现在想要给每位同学加一个称呼,那么我们把这个类改写一下

    1. class StudentDetail(DetailView):
    2. #指定数据集(过滤数据)
    3. #queryset = Student.objects.filter(sex='male')
    4. #指定模板路径
    5. template_name = 'student_detail.html'
    6. #指定object名称
    7. template_object_name = 'student'
    8. model = Student
    9. def get_context_data(self, **kwargs):
    10. context = super(StudentDetail,self).get_context_data(**kwargs)
    11. #获取当前的对象,就是加上了pk参数之后获得的Student对象实例
    12. student = kwargs.get('object',None)
    13. #取名字第一个字为姓(仅作示例,没考虑复姓情况)
    14. context['chenghu']= student.name[:1] + '大侠'
    15. return context

    student_detail.html里面加一行

    1. {% extends "base.html" %}
    2. {% block main %}
    3. <h2>姓名:{{ student.name }}h2>
    4. <p>年龄:{{ student.age }}p>
    5. <p>性别:{{ student.sex }}p>
    6. <p>成绩:{{ student.score }}p>
    7. <p>称呼:{{ chenghu }}p>
    8. {% endblock %}

    然后我们再访问一下  http://127.0.0.1:8000/student/5/,看到

     3、ArchiveIndexView

    django.views.generic.dates 模块中基于日期的通用视图用于显示基于日期的层次数据。

    其中 ArchiveIndexView 顶层索引页面,显示最新的对象(按日期排序)。

    如果未把 allow_future 设为 True,未来日期对应的对象不包含在内。

    我们还是做一个案例,把上面的那些同学按照年龄排列

    首先,修改models.py 中Student模型,增加一个bornDate字段,用来存放同学们的出生日期

    1. class Student(models.Model):
    2. id = models.IntegerField(primary_key=True)
    3. name = models.CharField(max_length=20,verbose_name='姓名')
    4. age = models.IntegerField(blank=True)
    5. sex = models.CharField(max_length=10)
    6. score = models.IntegerField (blank=True,default=0)
    7. bornDate = models.DateField(default='1996-01-22')

    然后在urls.py 文件中增加一个路由archive

    1. from django.contrib import admin
    2. from django.urls import path
    3. from newweb.views import *
    4. from classManage.views import *
    5. urlpatterns = [
    6. path('',classnotice),
    7. path('outdata',outdata),
    8. path('admin/', admin.site.urls),
    9. path('hello/',hello),
    10. path('student//',StudentDetail.as_view()),
    11. path('notice',classnotice),
    12. path('add/',addstudent),
    13. path('find/',findstudent),
    14. path('findall/',findall),
    15. path('findtj//',find_tj),
    16. path('modify/',modifystudent),
    17. path('del/',delstudent),
    18. path('displayMate/',display_meta),
    19. path('search/',chaxun3),
    20. path('cha/',chaxun4),
    21. path('sex_count/',sexCount),
    22. path('age_adult/',ageAult),
    23. path('yuanshi/',yuanshi),
    24. path('students/',StudentList.as_view()),
    25. path('archive/',ArchiveIndexView.as_view(model=Student, date_field="bornDate"),name="student_archive"),
    26. ]
    27. #这里的模型就用我们之间创建的Student,date_field是指定的用来排序的日期字段

    最后再展示一下

    1. {% extends "base.html" %}
    2. {% block main %}
    3. <ul>
    4. {% for student in latest %}
    5. <li>{{ student.name }} : {{ student.bornDate }} li>
    6. {% endfor %}
    7. ul>
    8. {% endblock %}

    然后访问 http://127.0.0.1:8000/archive/,看到 学生信息按照出生日期排序了

    另外还有 YearArchiveView  MonthArchiveView  WeekArchiveView DayArchiveView  TodayArchiveView  DateDetailView 等等用法也类似,就不展开了。

    4、FormView

    FormView是用来构建表单的通用视图,还记得我们在第八章((1条消息) <学习笔记>从零开始自学Python-之-web应用框架Django( 八)Django表单_阿尔法羊的博客-CSDN博客)里面做的那个查询表单嘛,我们现在用FormView来实现它。

    我们先找到form.py,改造一下,主要是增加一个查询用的函数 get_result

    1. from django import forms
    2. from classManage.models import Student
    3. from django.shortcuts import render
    4. class chaxunForm(forms.Form):
    5. name = forms.CharField(label="名字",max_length=10,required=False)
    6. age = forms.IntegerField(label="年龄",required=False,max_value=100,min_value=10)
    7. score = forms.IntegerField(label="成绩",required=False)
    8. def get_result(self):
    9. results=[]
    10. context={}
    11. stuName = self.cleaned_data.get('name')
    12. stuAge = self.cleaned_data.get('age')
    13. stuScore = self.cleaned_data.get('score')
    14. if stuName:
    15. stus=Student.objects.filter(name=stuName)
    16. elif stuAge:
    17. stus=Student.objects.filter(age=stuAge)
    18. elif stuScore:
    19. stus=Student.objects.filter(score=stuScore)
    20. else:
    21. pass
    22. for s in stus:
    23. result = '符合您查询条件的信息如下:姓名:{},年龄{},性别{},成绩{}'.format(s.name,s.age,s.sex,s.score)
    24. results.append(result)
    25. context['results']=results
    26. print(context)
    27. return context

    然后我们在 views.py 文件中创建一个类,继承FormView

    1. class chaXunView(FormView):
    2. initial = {'name':'郭靖','age':18} #初始值,可以在页面加载后看到
    3. template_name = 'chaxun.html' #指定模板
    4. form_class = chaxunForm #指定表单类
    5. success_url = '/chaxun/' #成功后跳转路径
    6. #extra_context={'title':'查询结果'} #额外的context内容

    FormView有很多内置方法,我们这里只要改写一下其中的 form_valid方法,用于获取我们查询到的结果,即判断form有效之后调用 form 的 get_result方法获取数据

    1. class chaXunView(FormView):
    2. initial = {'name':'姓名','age':18}
    3. template_name = 'chaxun.html'
    4. form_class = chaxunForm
    5. success_url = '/chaxun/'
    6. #extra_context={'title':'查询结果'}
    7. def form_valid(self, form):
    8. context=form.get_result()
    9. context['title']='查询结果'
    10. return self.render_to_response(context=context)

    然后在urls.py中加上一条路径

    1. 。。。。。。
    2. path('chaxun/',chaXunView.as_view(),name="student_chaxun"),
    3. 。。。。。。

    最后改造一下显示页面 chaxun.html,如果有查询结果就显示结果,否则显示表单

    1. {% extends "base.html" %}
    2. {% block title %}武侠三班的小窝{% endblock %}
    3. {% block main %}
    4. <h1>查询页面,在这里可以查找你想了解的同学h1>
    5. {% if title %}
    6. <h4>{{title}}h4>
    7. <P>
    8. {% for result in results %}
    9. <div>{{result}}div>
    10. {% endfor %}
    11. P>
    12. {% else %}
    13. <form action="" method="post">{% csrf_token %}
    14. <h3>根据条件查找同学h3>
    15. {{form}}
    16. <input type="submit" value="查询">
    17. form>
    18. {% endif %}
    19. {% endblock %}

    好了,我们访问下 http://127.0.0.1:8000/chaxun/

     可以看到默认值 ‘郭靖’ 和 18 已经显示在表单中,我们输入条件查询一下年龄为20的同学

     

    5、模型表单ModelForm

    处理模型时使用通用视图非常方便。只要能确定模型类,通用视图就能自动创建一个 ModelForm。

    确定模型类的方法如下:

    • 使用 model 属性指定的模型类。

    • 使用 get_object() 返回的对象所属的类。

    • 使用 queryset 对应的模型。

    模型表单视图提供的 form_valid() 能自动保存模型。如果有其他需求,可以覆盖这个方法。

    例如:我们设计一个页面用于录入学生信息,我们在views.py里面新建一个addStudent类

    1. class addStudent(ModelForm):
    2. class Meta:
    3. model = Student #对应的Model中的类
    4. fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段
    5. exclude = None #排除的字段
    6. labels = None #提示信息
    7. help_texts = None #帮助提示信息
    8. widgets = None #自定义插件
    9. error_messages = None #自定义错误信息
    10. #error_messages用法:
    11. error_messages = {
    12. 'name':{'required':"用户名不能为空",},
    13. 'age':{'required':"年龄不能为空",},
    14. }
    15. #labels,自定义在前端显示的名字
    16. labels= {
    17. "name":"用户名",
    18. "age":"年龄",
    19. "sex":"性别",
    20. "score":"得分",
    21. "bornDate":"生日",
    22. }

    然后定义一个add_student 视图函数,get方法用来获取页面,post方法用来获取前端传来的信息,然后用save()方法保存信息。

    1. def add_student(request):
    2. if request.method == 'GET':
    3. student_list = addStudent()
    4. return render(request,'addStudent.html',{'students':student_list},status=200)
    5. else:
    6. student_list = addStudent(request.POST)
    7. if student_list.is_valid():
    8. student_list.save()
    9. return render(request,'addStudent.html',{'student_list':student_list},status=200)

    然后还是在urls.py 里加上路径

    1. 。。。。。。
    2. path('add_student',add_student),
    3. 。。。。。。

    最后新建一个addStudent.html页面用于前端交互

    1. {% extends "base.html" %}
    2. {% block main %}
    3. <h2>添加学生h2>
    4. <div class="container" >
    5. <form method="POST" novalidate>
    6. {% csrf_token %}
    7. {# {{ students.as_p }}#}
    8. {% for student in students %}
    9. <div class="form-group col-md-6">
    10. {# 拿到数据字段的verbose_name,没有就默认显示字段名 #}
    11. <label class="col-md-3 control-label">{{ student.label }}label>
    12. <div class="col-md-9" style="position: relative;">{{ student }}div>
    13. div>
    14. {% endfor %}
    15. <div class="col-md-2 col-md-offset-10">
    16. <input type="submit" value="提交" class="btn-primary">
    17. div>
    18. form>
    19. div>
    20. {% endblock %}

    好,我们访问一下 http://127.0.0.1:8000/add_student

    一个录入信息的表格就做好了,我们填入数据,然后点击提交

     再访问查询数据

     

    CreateView, UpdateView, DeleteView 等用法类似,可以方便地实现创建、刷新、删除等功能

  • 相关阅读:
    随想005:调试的思考
    Python入门|零基础教程
    npm简单介绍
    自动化测试基础简介(本质)
    IDEA2021.2安装与配置(持续更新)
    Docker安装/使用Redis(可用/详细)
    大神都在用的Word文档技巧,你们快来学
    数据分析 第三周 (numpy数组的处理 , numpy数组的运用与画图的结合)笔记
    载薄荷醇纳米多孔PS微球/LA57接枝纳米炭黑修饰/Ag纳米粒子/聚苯乙烯微球性能相关研究
    联表查询之交叉连接、内、外连接
  • 原文地址:https://blog.csdn.net/qq_41597915/article/details/127754475