1.路由设计html
from django.conf.urls import url from django.contrib import admin from app import views from django.views import View urlpatterns = [ url(r'^admin/', admin.site.urls), # 基于类的视图 url(r'^login/', views.LoginView.as_view()), url(r'^logout/', views.LogoutView.as_view()), ]
2.模型设计git
from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): """ 用户信息表 """ nid = models.AutoField(primary_key=True) phone = models.CharField(max_length=11, null=True, unique=True, ) def __str__(self): return self.username class Meta: verbose_name = "用户信息" verbose_name_plural = verbose_name # 不要忘记在setting.py中引用Django的UserInfo表 # 引用Django自带的UserInfo表,继承使用时须要设置 AUTH_USER_MODEL = "app.UserInfo"
3.视图设计github
from django.views import View
class LoginView(View): def get(self, request, *args, **kwargs): form_obj = forms.LoginForm() return render(request, "login.html", {"form_obj": form_obj},) def post(self, request, *args, **kwargs): ret = {"code": 0} # 获取用户输入的用户名、密码 username = request.POST.get("username") password = request.POST.get("password") # 判断用户是否存在以及认证 user_obj = auth.authenticate(username=username, password=password) if user_obj: # 登陆 auth.login(request, user_obj) # 认证成功后可跳转的地址 ret["data"] = "/index/" else: # 认证失败 ret["code"] = 1 ret["data"] = "用户名或密码错误" return JsonResponse(ret) class LogoutView(View): # 退出登陆 def get(self, request, *args, **kwargs): auth.logout(request) return redirect("/login/")
1.基于函数的视图中,URL设计中,当接收到客户端请求时根据正则匹配获得相应的视图函数并执行,而后获得相应的HttpResponse响应django
url(r'^login/', views.login),
2.基于类的视图中,最终也是将函数的执行结果返回给客户端,不一样的是当接收到客户端请求时,根据类调用类中的方法,由类的继承、封装、多态、属性查找等特性最终获得相应的HttpResponse响应app
url(r'^login/', views.LoginView.as_view()),
看源码(展现中将部分源码省略):函数
1)客户端发起请求,省略前边一系列中间件等流程,进行路由解析的时候,经过路由匹配拿到对应的类,发现post
拿到的是一个对象.属性的方法,因而进行类的属性查找网站
class LoginView(View): def get(self, request, *args, **kwargs): ... def post(self, request, *args, **kwargs): ...
2)发现该视图类中没有 as_view() 这个方法,因而根据属性查找关系到继承的类View中查找url
class View(object): http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] @classonlymethod def as_view(cls, **initkwargs): def view(request, *args, **kwargs): return self.dispatch(request, *args, **kwargs) return view
3)函数中的self为当前的访问到的LoginView对象,在上面的view()方法中返回时遇到self.dispatch(),因而有通过一次属性查找,子类中找不到又再次来到View父类中查找dispatch()方法,最终获得如下spa
def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed)return handler(request, *args, **kwargs)
4)最终经过反射的方式从View类定义的HTTP请求方法和类视图LoginView中对应的方法,获取到HttpResponse响应返回给客户端
以上是Django中内置的类视图方法,还能够经过安装restframework模块,继承其模块内的APIView类实现:
1)APIView实际上继承的也是Django内置的View类
2)获取HttpResponse响应返回给客户端的过程与以前解析的方法相同,区别在于通过属性查找原则最终调用dispatch()方法时,调用的是REST framework内的自定义的dispatch()
def dispatch(self, request, *args, **kwargs): """ `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """ self.args = args self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers # deprecate? try: self.initial(request, *args, **kwargs) # Get the appropriate handler method 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 response = handler(request, *args, **kwargs) except Exception as exc: response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs) return self.response
经过属性查找等规则,最后获得一个HttpResponse相应,不一样的是在使用REST famework模块时,可在调用dispatch()方法时实现REST framework提供的其它功能
官方网站:
http://www.django-rest-framework.org/
第三方翻译的中文文档:
https://q1mi.github.io/Django-REST-framework-documentation/