Django中的使用render()渲染模板以及前后端的信息交互

render真的是Django框架中的一个神奇的函数,到目前为止,在我的理解里,它是负责前端页面和后端逻辑之前传出数据。

首先看看网上别人的理解,参考链接:http://www.cnblogs.com/panwenbin-logs/p/5838064.html

别的不说先上源码:(这里Django版本是1.9)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def render(request, template_name, context=None,
context_instance=_context_instance_undefined,
content_type=None, status=None, current_app=_current_app_undefined,
dirs=_dirs_undefined, dictionary=_dictionary_undefined,
using=None):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
Uses a RequestContext by default.
"""
if (context_instance is _context_instance_undefined
and current_app is _current_app_undefined
and dirs is _dirs_undefined
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
# In Django 1.10, request should become a positional argument.
content = loader.render_to_string(
template_name, context, request=request, using=using)
else:
# Some deprecated arguments were passed - use the legacy code path
if context_instance is not _context_instance_undefined:
if current_app is not _current_app_undefined:
raise ValueError('If you provide a context_instance you must '
'set its current_app before calling render()')
else:
context_instance = RequestContext(request)
if current_app is not _current_app_undefined:
warnings.warn(
"The current_app argument of render is deprecated. "
"Set the current_app attribute of request instead.",
RemovedInDjango110Warning, stacklevel=2)
request.current_app = current_app
# Directly set the private attribute to avoid triggering the
# warning in RequestContext.__init__.
context_instance._current_app = current_app
content = loader.render_to_string(
template_name, context, context_instance, dirs, dictionary,
using=using)
return HttpResponse(content, content_type, status)

参考链接: http://www.ziqiangxuetang.com/django/django-json-templates.html

首先我们想传递一个dict或者list传递给JavaScript,处理之后显示到网页上,比如要用js进行可视化数据。有两种方法:

一种就是我这几天在用的render方法,这个方法需要在视图函数中使用(也就是应用下面的views.py文件中使用),和网页其他的部分一起渲染到网页上(一次性地渲染,还是同一次请求)。

看例子:先是views.py

1
2
3
4
5
6
from __future__ import unicode_literals
from django.shortcuts import render
def home(request):
List = ['自强学堂', '渲染Json到模板']
return render(request, 'home.html', {'List': List})


参考链接: http://www.cnblogs.com/feixuelove1009/p/5922347.html

render()函数的第一个位置参数是请求对象(就是view函数的第一个参数),第二个位置参数是模板,还可以有一个可选的第三参数—一个字典,包含需要传递给模板的数据。最后render函数返回一个经过字典数据渲染过的模板封装而成的HttpResponse对象。

也就是说render的参数中只能有一个dict类型的对象。如果像之前尝试的那样传进去两个字典作为参数,就会报错,==AttributeError ‘dict’ object has no attribute ‘push’==,具体我也不知道字典类型的变量到底具有什么属性。

接下来继续探索,就是我们在视图函数中将一些内容传到前端页面,具体传了什么呢?

这里以用户注册为例:视图函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class RegisterView(View):
def get(self, request):
register_form = RegisterForm()
return render(request, "register.html", {'register_form':register_form})
def post(self, request):
register_form = RegisterForm(request.POST)
if register_form.is_valid():
user_name = request.POST.get("email", "")
if UserProfile.objects.filter(email = user_name):
return render(request, "register.html", { "register_form": register_form, "msg": "用户已经存在" })
pass_word = request.POST.get("password", "")
user_profile = UserProfile()
user_profile.username = user_name
user_profile.email = user_name
user_profile.is_active = False
user_profile.password = make_password(pass_word)
user_profile.save()
send_email(user_name, "register")
return render(request, "login.html")
else:
return render(request, "register.html", {"register_form": register_form })

我们开始调试,按照要求填入信息,调试之后得到的
一些中间过程的内容:

这是我们得到的request的内容,其实request是一个字典类型的值:

image

接下来是填入信息之后得到的前端传来的数据填写的表单,也就是register_form(这里思考一个问题,表单是什么类型的值呢?):

image

在接下来后端接收了数据,并且从数据库中根据email查找用户,获取到的email被赋值给了变量user_name:

image

发现没查找到,这就说明这个邮箱之前是没有注册过账户的,这次注册是合法的,所以向数据库中的用户信息表(在我的项目中是UserProfile数据表)插入一条数据,获取到所有的数据后得到的要插入的数据是:

image

这里就是我们从前端页面获取到数据,在后端处理之后存入数据库的过程。


接下来就说一下前端页面请求数据的时候,后端是怎样将数据传到前端用于显示的。

看代码:

1
return render(request, "register.html", {"register_form": register_form })

这段代码是发生在用户在注册页面中填入的数据出错的时候,用户要继续留在注册界面,并且要将发生的错误显示到前端页面中以提示用户,看前端的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div class="tab-form">
<form id="email_register_form" method="post" action="{% url 'register' %}" autocomplete="off">
<input type='hidden' name='csrfmiddlewaretoken' value='gTZljXgnpvxn0fKZ1XkWrM1PrCGSjiCZ' />
<div class="form-group marb20 {% if register_form.errors.email %}errorput{% endif %}">
<label>邮&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱</label>
<input type="text" id="id_email" name="email" value="" placeholder="请输入您的邮箱地址" />
</div>
<div class="form-group marb8 {% if register_form.errors.password %}errorput{% endif %}">
<label>密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码</label>
<input type="password" id="id_password" name="password" value="" placeholder="请输入6-20位非中文字符密码" />
</div>
<div class="form-group marb8 captcha1 {% if register_form.errors.password %}errorput{% endif %}">
<label>验&nbsp;证&nbsp;码</label>
{{ register_form.captcha }}
<!--<img src="/captcha/image/2f3f82e5f7a054bf5caa93b9b0bb6cc308fb7011/" alt="captcha" class="captcha" /> <input id="id_captcha_0" name="captcha_0" type="hidden" value="2f3f82e5f7a054bf5caa93b9b0bb6cc308fb7011" /> <input autocomplete="off" id="id_captcha_1" name="captcha_1" type="text" />-->
</div>
<div class="error btns" id="jsEmailTips">{% for key,error in register_form.errors.items %}{{ error }}{% endfor %}{{ msg }}</div>
<div class="auto-box marb8">
</div>
<input class="btn btn-green" id="jsEmailRegBtn" type="submit" value="注册并登录" />
<input type='hidden' name='csrfmiddlewaretoken' value='5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy' />
{% csrf_token %}
</form>
</div>

这里我们在显示错误信息到前端页面的时候用到了register_form中的错误,每次出错的时候就会将错误都显示出来,而register_form的内容就是通过render()函数传过来的。

目前就是这些收获,未完待续