2018-12-29

FBV & CBV

FBV (Function-Based-View):在视图里使用函数处理请求
CBV (Class-Based-View):在视图里使用类处理请求

# views.py
from django.http import HttpResponse
from django.views import View
  
class MyView(View):

      def get(self, request):
            return HttpResponse('OK, get')

      def post(self, request):
            return HttpResponse('OK, post')

# Django的url是将一个请求分配给可调用的函数的,而不是一个class。
# 针对这个问题,class-based view提供了一个as_view()静态方法(也就是类方法),调用这个方法,会创建一个类的实例,然后通过实例调用dispatch()方法,dispatch()方法会根据request的method的不同调用相应的方法来处理request(如get() , post()等)。
# 到这里,这些方法和function-based view差不多了,要接收request,得到一个response返回。如果方法没有定义,会抛出HttpResponseNotAllowed异常。
# urls.py
# urls.py
from django.conf.urls import url
from myapp.views import MyView
  
urlpatterns = [
     url(r'^index/$', MyView.as_view()),
]
  • 类的 属性 可以通过两种方法设置
    (1) 常见的Python的方法,可以被子类覆盖。
from django.http import HttpResponse
from django.views import View
  
class GreetingView(View):
    name = "yuan"
    def get(self, request):
         return HttpResponse(self.name)
  
# You can override that in a subclass
  
class MorningGreetingView(GreetingView):
    name= "alex"

(2) url中设置类的属性

urlpatterns = [
   url(r'^index/$', GreetingView.as_view(name="egon")),
]

应用:登录验证

----------------应用:登录验证
   
   继承:
        单继承:
            # class BaseView(View):
            #     def dispatch(self, request, *args, **kwargs):
            #         if request.session.get('username'):
            #             response = super(BaseView,self).dispatch(request, *args, **kwargs)
            #             return response
            #         else:
            #             return redirect('/login.html')
            #
            # class IndexView(BaseView):
            #
            #     def get(self,request,*args,**kwargs):
            #         return HttpResponse(request.session['username'])
写一个类继承VIEW 调用View 的dispath 函数之前做一个 session验证

多继承:

# 多继承方式:
# class BaseView(object):
#     def dispatch(self, request, *args, **kwargs):
#         if request.session.get('username'):
#             response = super(BaseView,self).dispatch(request, *args, **kwargs)
#             return response
#         else:
#             return redirect('/login.html')
#
# class IndexView(BaseView,View):
#
#     def get(self,request,*args,**kwargs):
#         return HttpResponse(request.session['username'])

和上面的方法原理相同, 自己写的类BaseView不继承任何类, 然后主类 继承 自己写的类 和 View 类,BaseView中的super方法 会找到 View 中的dispath 

装饰器:
   
   def auth(func):
      def inner(request,*args,**kwargs):
         if request.session.get('username'):
            obj = func(request,*args,**kwargs)
            return obj
         else:
            return redirect('/login.html')
      return inner

   
   # @method_decorator(auth,name='get')
   class IndexView(View):
      
      @method_decorator(auth)
      def dispatch(self, request, *args, **kwargs):
         if request.session.get('username'):
            response = super(IndexView,self).dispatch(request, *args, **kwargs)
            return response
         else:
            return redirect('/login.html')

      @method_decorator(auth)
      def get(self,request,*args,**kwargs):
         return HttpResponse(request.session['username'])
         
      @method_decorator(csrf_exempt)  # 无效
      def post(self,request,*args,**kwargs):
         return HttpResponse(request.session['username'])
要注意俩点:
    1:用的 CBV 的话 需要导入 from django.utils.decorators import method_decorator  之后@method_decorator(auth)
    放在函数名上,   如果放在类上需要加个参数  @method_decorator(auth,name='get') ,说明是 给 get函数使用 
   2:但是django有个BUG 装饰器方法都会出现 CSRF问题 ,所以
    需要写一个dispath方法 直接调用VIEW里面的 dispath 进行反射@method_decorator(auth) 放在 dispath上面

serializers序列化

  • json.dumps():将字典转为字符串
  • serializers.serialize():将QuerySet等类型转为字符串
   方式一:
      user_list = models.UserInfo.objects.all()
      data = serializers.serialize("json", user_list)
      [
         {"model": "app01.userinfo", "pk": 1, "fields": {"username": "\u5174\u666e", "password": "123123"}}, 
         {"model": "app01.userinfo", "pk": 2, "fields": {"username": "\u94f6\u79cb\u826f", "password": "666"}}
      ]

由于json.dumps 不能对 QuerySet 类型进行处理, 所以 要使用 serializers.serialize  ;但是处理结果往往不太理想

      
   方式二:
      
      user_list = models.UserInfo.objects.values('id','username')
      user_list = list(user_list)
      data = json.dumps(user_list)
      [
         {"username": "\u5174\u666e", "id": 1}, 
         {"username": "\u94f6\u79cb\u826f", "id": 2}
      ]
  所以我们可以 用list 将QuerySet 类型转变为List类型
      
      问题:对json.dumps做定制:

  如果要json的列表中有不能处理的字段类型,比如datetime,date
  那么就需要帮它们转换一下,
  在json.dumps 的命令中 可以多增加一个参数,cls=一个类
  这个类继承 json.JSONEncoder,如下
         
            import json
            from datetime import date
            from datetime import datetime

            class JsonCustomEncoder(json.JSONEncoder):
               def default(self, field):
                  if isinstance(field, datetime):
                     return field.strftime('%Y-%m-%d %H:%M:%S')
                  elif isinstance(field, date):
                     return field.strftime('%Y-%m-%d')
                  else:
                     return json.JSONEncoder.default(self, field)


            user_list = [
               {'id':1,'name':'alex','ctime': datetime.now()},
               {'id':2,'name':'eric','ctime': datetime.now()}
            ]

            data = json.dumps(user_list,cls=JsonCustomEncoder)
            print(data)
就可以帮助我们处理 datetime,date类型了,其他类型,当然也可以,修改类里面就ok

你可能感兴趣的:(2018-12-29)