Django中url中可以使用类视图.as_view()进行映射的原因
Posted jj1106
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django中url中可以使用类视图.as_view()进行映射的原因相关的知识,希望对你有一定的参考价值。
说明:本人在学练习天天生鲜项目时,对利用类视图去与正则匹配到的url做映射有点疑惑,经过查看他人博客以及自我分析算是整明白了,所以记录一下
参考:https://www.zmrenwu.com/post/53/
HTTP发送请求的方式有很多种,这里以POST,GET为例。当在浏览器中输入url地址时(如http://127.0.0.1:8000/userr/register)
会进行正则匹配,并映射到ActiveView.as_view(),其最终达到能将注册页面显示出来的效果,原因如下:
class RegisterView(View): ‘‘‘注册‘‘‘ def get(self, request): ‘‘‘显示注册页面‘‘‘ return render(request, ‘register.html‘) def post(self, request): ‘‘‘进行注册处理‘‘‘ ‘‘‘进行注册处理‘‘‘ # 接收数据 username = request.POST.get(‘user_name‘) password = request.POST.get(‘pwd‘) email = request.POST.get(‘email‘) allow = request.POST.get(‘allow‘) # 进行数据处理 if not all([username, password, email]): return render(request, ‘register.html‘, ‘errmsg‘: ‘数据不完整‘) # 校验邮箱 if not re.match(r‘^[a-z0-9][\\w.\\-]*@[a-z0-9\\-]+(\\.[a-z]2,5)1,2$‘, email): return render(request, ‘register.html‘, ‘errmsg‘: ‘邮箱格式不正确‘) # 校验协议 if allow != ‘on‘: return render(request, ‘register.html‘, ‘errmsg‘: ‘请同意协议‘) # 校验用户名是否重复 try: user = User.objects.get(username=username) except User.DoesNotExist: # 用户不存在 user = None # 进行业务处理: 进行用户注册 user = User.objects.create_user(username, email, password) user.is_active = 0 user.save() # 发送激活邮件 serializer = Serializer(settings.SECRET_KEY, 3600) info = ‘confirm‘:user.id token = serializer.dumps(info) # bytes token = token.decode() # 发邮箱 send_register_active_email.delay(email, username, token) # subject = ‘天天生鲜欢迎信息‘ # message = ‘‘ # sender = settings.EMAIL_FROM # receiver = [email] # html_message = ‘<h1>%s, 欢迎您成为天天生鲜注册会员</h1>请点击下面链接激活您的账户<br/><a href="http://127.0.0.1:8000/userr/active/%s">http://127.0.0.1:8000/userr/active/%s</a>‘ % ( # username, token, token) # send_mail(subject, message, sender, receiver, html_message=html_message) # 返回应答,跳转到首页 return redirect(reverse(‘goods:index‘))
RegisterView类中并没有as_view()方法,但其父类View中有as_view()方法,所以父类的此方法就被调用,父类View原码如下
class View(object): """ Intentionally simple parent class for all views. Only implements dispatch-by-method and simple sanity checking. """ http_method_names = [‘get‘, ‘post‘, ‘put‘, ‘patch‘, ‘delete‘, ‘head‘, ‘options‘, ‘trace‘] def __init__(self, **kwargs): """ Constructor. Called in the URLconf; can contain helpful extra keyword arguments, and other things. """ # Go through keyword arguments, and either save their values to our # instance, or raise an error. for key, value in six.iteritems(kwargs): setattr(self, key, value) @classonlymethod def as_view(cls, **initkwargs): """ Main entry point for a request-response process. """ for key in initkwargs: if key in cls.http_method_names: raise TypeError("You tried to pass in the %s method name as a " "keyword argument to %s(). Don‘t do that." % (key, cls.__name__)) if not hasattr(cls, key): raise TypeError("%s() received an invalid keyword %r. as_view " "only accepts arguments that are already " "attributes of the class." % (cls.__name__, key)) def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, ‘get‘) and not hasattr(self, ‘head‘): self.head = self.get self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) view.view_class = cls view.view_initkwargs = initkwargs # take name and docstring from class update_wrapper(view, cls, updated=()) # and possible attributes set by decorators # like csrf_exempt from dispatch update_wrapper(view, cls.dispatch, assigned=()) return view def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn‘t exist, # defer to the error handler. Also defer to the error handler if the # request method isn‘t on the approved list. if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) def http_method_not_allowed(self, request, *args, **kwargs): logger.warning( ‘Method Not Allowed (%s): %s‘, request.method, request.path, extra=‘status_code‘: 405, ‘request‘: request ) return http.HttpResponseNotAllowed(self._allowed_methods()) def options(self, request, *args, **kwargs): """ Handles responding to requests for the OPTIONS HTTP verb. """ response = http.HttpResponse() response[‘Allow‘] = ‘, ‘.join(self._allowed_methods()) response[‘Content-Length‘] = ‘0‘ return response def _allowed_methods(self): return [m.upper() for m in self.http_method_names if hasattr(self, m)]
dispatch()方法实现的功能如下:
首先它通过 request.method
(即 HTTP 请求的方法)判断请求的方法是否是被 HTTP 协议所允许的。如果不合法,就会调用错误处理函数 self.http_method_not_allowed
;如果请求方法是合法的,就会试图根据 request.method
去类中寻到对应的处理方法,如果找不到则还是委托给 self.http_method_not_allowed
处理。
代码实现过程:
当在浏览器中输入url地址时(如http://127.0.0.1:8000/userr/register),经过正则匹配以及映射关系,首先调用View.as_view()方法,接着调用as_view()方法中的view()方法,view()方法进一步调用View类内的dispatch()方法。,在dispatch()方法中,request.method判断出HTTP请求的方法为GET,request.method.lower()将GET转换为get,getattr方法将得到的get负值给handler,然后通过return handler()调用handler()方法,即为RegisterView类中的get()方法,而get()方法会返回模板中的html文件(即register.html)。其返回的结果依次return给方法的调用者,最终返回给View.as_view()方法的结果是模板中的register.html文件,即能显示出注册页面,如下
当点击注册时(填好相关信息),此时HTTP的请求方式变成POST,同理,最终也能显示出相应的页面(此处为显示首页)
以上是关于Django中url中可以使用类视图.as_view()进行映射的原因的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Django 2.0 中使用波斯语蛞蝓解码 URL?