• 3、django视图层


    #前言:视图逻辑怎么分块儿都可以。只要你的路由能找到就行。#

    1、CBV(class base views)模式和FBV(function base views)模式

      顾名思义。一个在views里面写函数。一个在views里写类方法。

      CBV具体格式如下:

      urls代码:  

    from django.urls import path,re_path
    from CBV_app import views
    
    urlpatterns = [
        path('login/', views.Login.as_view()),
        path('starter/', views.Starter.as_view()),
    ]

      views代码:

    class Login(View):
    
        def get(self, request):
            return HttpResponse("ok")
        
        def post(self, request):
            pass
        
        
    class Starter(View):
        def get(self, request):
            return render(request, 'base.html')
        
        def post(self, request):
            pass

      如上:CBV与FBV相比好处就是。是用class的方式编写,可以使用面向对象的好处。如多继承,反射等等。

      且继承的view类中的dispatch方法帮我们写了请求分发。我们只需要把自己的方法名写成对应请求类型即可(如上)。不用再去判断请求类型。

      view部分源码截取如下:

    class View:
        """
        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 kwargs.items():
                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)

    2、request和response

      请求数据平常使用较多的有。cookies、session、token、body参数、user-agent等等。(META可以拿ip),无需再看

      响应在views中主要有三种形式。HttpResponse()、render()、redirect()、

        HttpResponse()就返回一个具体的字符串。没有什么好说的。

        render()、源码如下:

    def render(request, template_name, context=None, content_type=None, status=None, using=None):
        """
        Return a HttpResponse whose content is filled with the result of calling
        django.template.loader.render_to_string() with the passed arguments.
        """
        content = loader.render_to_string(template_name, context, request, using=using)
        return HttpResponse(content, content_type, status)

          1、request,用于生成响应的请求对象。

          2、template_name,要使用的模板的完整名称,可选

          3、context,添加到模板的一个字典,如果不为空。则在渲染之前调用。(多用于前后端不分离项目)

        redirect()

          如下代码。一个很简陋的demo。校验IP访问频率。次数过多重定向。

    class AccessFrequencyVerification2(MiddlewareMixin):
        """
        做访问频率校验。
        1、每次登录。在表里面查询有无该ip的访问记录。
        2、如果没有。记录ip、访问时间。 访问次数写成1
        3、如果表里面查询有该IP的访问记录。且访问时间距当前时间小于60s,则访问次数+1。大于则把访问次数写为0。
        4、访问之前判断次数有没有大于20。如果大于,请求接到一个独立页面。
        """
        def process_request(self, request):
            if request.path in ["/error/"]:
                return None
            else:
                if request.META.get('HTTP_X_FORWARDED_FOR'):
                    ip = request.META.get("HTTP_X_FORWARDED_FOR")
                else:
                    ip = request.META.get("REMOTE_ADDR")
    
                a = AccessFrequencyVerification.objects.filter(ip=ip).first()
                if a is None:
                    # 新用户插入数据逻辑
                    time = timezone.now()
                    AccessFrequencyVerification.objects.create(
                        ip=ip,
                        Access_time=time,
                        Number_visits=1,
                    )
                else:
                    # 老用户处理逻辑
                    Access_time = AccessFrequencyVerification.objects.filter(ip=ip).first().Access_time
                    time = timezone.now()
                    time_difference = time-Access_time
                    a = AccessFrequencyVerification.objects.filter(ip=ip).first().Number_visits
                    b = datetime.timedelta(seconds=60)
                    if time_difference < b:
                        # 60s之内连续登录
                        AccessFrequencyVerification.objects.filter(ip=ip).update(Number_visits=a+1)
                    else:
                        # 60s之后登录
                        AccessFrequencyVerification.objects.filter(ip=ip).update(Access_time=time)
                        AccessFrequencyVerification.objects.filter(ip=ip).update(Number_visits=0)
                    if a > 20:
                        return redirect("/error/")
                    else:
                        return None

        当然,重定向也可以写一个完成URL。

         

  • 相关阅读:
    测试
    CF868F Yet Another Minimization Problem
    MySQL常用命令
    mysql 5.7.18 winx64安装配置方法
    重装win7系统并激活
    JAVA创建子进程并处理waitFor() 阻塞问题
    Some code changes cannot be hot swapped into a running virtual machine
    java开发手册(阿里巴巴)——编程规约(部分)
    java——File
    OpenModelica Debug
  • 原文地址:https://www.cnblogs.com/cbslock/p/12145579.html
Copyright © 2020-2023  润新知