知识点:
locals()可以将局部变量以字典的方式打包状态码 2xx 成功3xx 重定向 301 永久转移302 暂时转移 4xx 客户端错误5xx 服务端错误在Student类中定义一个方法:
class Student(models.Model): s_name = models.CharField(max_length=16) def get_name(self): return self.s_name 通过.访问方法: {% for student in students %} <li> {{ student.get_name }} </li> {% endfor %}之前用for的时候如果迭代器里没有数据那么在网页上是不会有输出的,现在想即使没有可输出的东西也有个提示,就要使用empty:
{% for student in students %} <li> {{ student.s_name }} </li> {% empty %} <h2>查无此人</h2> {% endfor %}可以在循环时记录次数:
{% for student in students %} <li> {{ forloop.counter }}:{{ student.get_name }} </li> {% endfor %} 结果: 1:Ming0 2:Ming1 3:Ming2 4:Ming3 5:Ming4 6:Ming5 7:Ming6 8:Ming7 9:Ming8 10:Ming9first的使用,如果是第一个数据,就将其变色:
{% for student in students %} {% if forloop.first %} <li style="color: #0000ff">{{ student.s_name }}</li> {% else %} <li>{{ student.s_name }}</li> {% endif %} {% endfor %}之前的注释是:
<!-- -->这样写在网页上能看到,下面的写法看不到:
{# #} # 单行 {% comment %} ... {% endcomment %} # 多行加减 使用{% 要加减的数|add 加减多少 %}
{{ count|add:2 }} {{ count|add:-2 }}乘除 使用{% widthratio 数 分母 分子 %}:
<h3>{% widthratio count 1 5 %}</h3> 结果是25整除 {% if num|divisibleby:要整除的数 %},== |左右不能加空格?我加了报错…==
{% for student in students %} {% if forloop.counter|divisibleby:2 %} <li style="color: #0000ff">{{ student.s_name }}</li> {% else %} <li style="color: red">{{ student.s_name }}</li> {% endif %} {% endfor %}两数相等/不相等 {% ifequal/ifnotequal value1 value2 %}
{% for student in students %} {% ifequal forloop.counter 5 %} <li style="color: #0000ff">{{ student.s_name }}</li> {% else %} <li style="color: red">{{ student.s_name }}</li> {% endifequal %} {% endfor %} 第五行变蓝,其它变红大/小写转换
<h3>{{ info.hobby|lower }}</h3> <h3>{{ info.hobby|upper }}</h3>示例如下:
先创建一个文件,base.html,使用block来布局 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{{ title }}</title> </head> <body> {% block header %} {% endblock %} {% block banner %} {% endblock %} {% block content %} {% endblock %} {% block footer %} {% endblock %} </body> </html> 再创建home.html,使用extends继承base.html {% extends 'base.html' %} {% block header %} <h3>This is head.</h3> {% endblock %} {% block footer %} <h3>This is footer</h3> {% endblock %} 在views中: def temp(request): return render(request, 'home.html', context={'title': ' Home'}) include: {% include 'footer.html' %}但要注意,父类通过block挖的坑,子类只能在这些坑里填数据,否则会被优化掉不显示
视图的响应分两类:
以json形式返回以网页形式返回 (40X, 50X)重定向到另一个网页在Django1.1版本,是按照列表的书写顺序进行匹配的,并且没有最有匹配的概念(即上条是haha,下条是hahaha,那么输入hahaha会匹配上面那条),但是在2.2版本已经解决了。
如果想在查询的时候传参数:
在1.1版本中是用正则来做的,但在2.2中使用了path,如果还想使用正则,可以用re_path
urlpatterns = [ path('student/<int:num><str:s>/', views.student), ] views: def student(request, num, s): print(num, s) print(type(num), type(s)) return HttpResponse('get student successful!') 在调用时: http://127.0.0.1:8000/Two/student/2m/ 结果: 2 m <class 'int'> <class 'str'>然后写urls,要先进入到班级列表界面:
urls: path('grade/', views.grade), views: def grade(request): grade_list = Grade.objects.all() return render(request, 'grade_list.html', context=locals()) grade_list.html: <body> <ul> {% for grade in grade_list %} <li><a href="/Two/students/{{ grade.id }}/">{{ grade.g_name }}</a></li> {% endfor %} </ul> </body>这里给每个班级加了a标签以便跳转,而跳转到的地址就应该显示具体的学生信息,那么我们根据每次循环可以得到每个班级的id,以此作为参数写入a标签中。 在urls中写入a标签跳转过来的地址:
path('students/<int:g_id>/', views.students) views: def students(request, g_id): res = Student.objects.filter(s_grade_id=g_id) return render(request, 'student_grade.html', context=locals()) student_grade.html: <ul> {% for re in res %} <li>{{ re.s_name }} : {{ re.s_grade.g_name }}</li> {% endfor %} </ul>之前的url都是写死的,但是当名称更改时所有相关的代码都要更改,这就很麻烦了,因此引入了反向解析。
来看html文件,上一行是写死的方法,下一行是反向解析,具体意思是: 在主urls中在more/这个url后面加了一个namespace,然后在从urls中指定了name,这就相当于起了个别名,我们在模板中使用时的形式为:{% url ‘namespace:name’ %},在渲染时会自动的找到相应的view方法。
今天在这块卡了好久,我以为改名之后在浏览器里输入新名字也能访问,但是却报404,查了好久,后来才知道这个name是用于模板语法的,也就是只能在模板中这么用,或者在python代码中也可以用,但要用reverse(),所以我在浏览器中这么干肯定是不行的
前面说到了带参数的路由,那么同样可以用到这里:
path('get_time/<int:year><int:month><int:day>', views.get_time, name='gtime'), def get_time(request, year, month, day): return HttpResponse("Time %s %s %s" % (year, month, day)) <a href="{% url 'test:gtime' 2020 7 1%}">Time</a>通过点击Time选项即可跳转到get_time方法进而返回内容。
reverse()
url: path('hello/', views.hello, name='hi'), views: def buy(request): url = reverse('App:hi') return HttpResponseRedirect(url)如果要带参数,则:
位置参数:reverse(‘namespace:name’, args=(value1, value2, …))关键字参数:reverse(‘namespace:name’, kwargs={key1:value1, key2:value2, …}当出现404界面时,可以重写它,在templates下新建一个名为404的html文件即可。
服务器收到Http请求后,会根据报文创建HttpRequest对象,也就是view中的第一个参数。
方法如下:
属性方法释义method请求的方法,GET,POSTencoding编码,常用utf-8GET字典形式,包含get所有参数POST字典形式,包含post所有参数FILES字典形式,包含上传的文件COOKIES字典形式,包含cookiesession字典形式,回话is_ajax()判断是否ajax()运行结果如下:
/more/show_request/ GET <QueryDict: {}> <QueryDict: {}> 可以看到路径,方法是GET,由于没传参所以第三行为空,由于不是POST请求,所以第四行为空现在稍作更改,在地址栏写http://127.0.0.1:8000/more/show_request/?age=17&age=18,结果如下
/more/show_request/ GET <QueryDict: {'age': ['17', '18']}> <QueryDict: {}> 既然QueryDict是类字典,那么就可以像字典那样访问:request.GET.get(‘key名称’)即可得到value,但这样只能得到最后一个value;若想得到所有则要用request.GET.getlist(‘key名称’)
要验证post则先要弄个表单:
<form action="" method="post"> <span>UserName:</span> <input type="text" name="username" placeholder="请输入用户名"> <button>Submit</button> </form> urls: path('show_post/', views.show_post), views: def show_post(request): return render(request, 'post.html')点击后会报错,CSRF验证失败. 请求被中断。目前还没学,等后面学完了再来看看。 暂时的解决方案:主文件夹->settings->‘django.middleware.csrf.CsrfViewMiddleware’,屏蔽掉即可 运行结果:
/more/create/ POST <QueryDict: {}> <QueryDict: {'username': ['jack']}>使用request.META可以访问客户端的所有信息,包括ip、主机名…