美文网首页
django里的那些事儿

django里的那些事儿

作者: 清风徐来_简 | 来源:发表于2019-05-17 12:36 被阅读0次

一、CBV版视图
二、给视图加装饰器
三、request对象常用属性
四、url:路由系统
五、命名url和url的反向解析
六、session
七、使用 pymysql 连接 mysql
八、内置auth认证
九、模板语法中的for循环

django官方文档:django-documentation

  • 一、CBV版视图

    veiw中写函数有两种写法,之前写的def类都是FBV版。还有一种写法是CBV版。就是将之前函数的写法变类的写法,url中也要相应变动一下。

    例:

    视图中定义:
       from django.views import View
    
       Class AddBook(View):
           def dispatch(self, request, *args, **kwargs):
               print('处理请求之前')
               ret = super().dispatch(request, *args, **kwargs)
               print('处理请求之后')
               return ret
           def get(self,request):
               pass
           def post(self,request):
               pass
    
    url中使用:
        url(r'^add_book/$',views.AddBook.as_view())
    
    执行过程:
           1,AddBook这个类,执行了as_view()这个方法,但是,我们自定义的类里没有写这个方法;
              这就要看继承的父类里,View类有没有了,查看,有此方法,是类方法。
    
           2,这个类方法执行到最后返回了一个view函数,不带括号,没有执行,等待连接后才执行。
                 
           3,view函数执行到最后返回了一个dispatch函数且执行后的结果。
              self = cls(**initkwargs) 实例化了一个对象
              return self.dispatch(request, *args, **kwargs)
              此时如果自己写的类里有dispatch方法则会执行自己的,没有则会执行父类的
                 
           4,dispatch(派遣的意思)函数过程中对接收到的请求方式进行了判断,并对其进行了反射,
              handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
              反射得出方法
              如果是get则执行get函数,如果是post则执行post函数,并将执行结果返回。
              return handler(request, *args, **kwargs)
              执行并返回结果
              父类的dispatch(self, request, *args, **kwargs):方法
              是执行自己写的get/post函数的一个过程。
    
    
    理解dispatch:
              上述分析,函数走到dispatch后,是一个对象方法,如果在自己的类里写了此方法,那么他会走自己的方法。
              但是,父类有这个方法为什么还要自己写呢?走自己的方法有什么用呢?
              那就要看你的需求了,函数走到那一步就会走dispatch这个函数,
              如果自己感觉累了,想要先停一会儿,你就停几分钟,过一会儿再拿过来父类的dispatch运行,
              因为你自己的dispatch方法没有父类的功能,所以还得借用父类的dispatch方法。
    
    
    简版的流程:
             AddPublisher.as_view()   ——》 view 函数
             当请求来的时候才执行view
             view中执行:
                   1. 先实例化AddPublisher,给self
                   2. 执行self.dispatch()
                      self 有dispatch 就执行自己的
                      没有就是执行 父类(View)的dispatch方法
                   3. dispatch中执行:
                      先通过反射获取到AddPublisher中定义get或者post方法。
                      执行get或者post方法 返回httpresponse对象
                   4. view接收到dispatch的返回值——httpresponse对象
                   5. view返回httpresponse对象
    
  • 二、给视图加装饰器

    装饰器:
          def wrapper(func):
              def inner(*args, **kwargs):
                  start_time = time.time()
                  ret = func(*args, **kwargs)
                  end_time = time.time()
                  print("used:", end_time-start_time)
                  return ret
              return inner
    
    # FBV版添加装饰器
    @wrapper
    def add_class(request):
        if request.method == "POST":
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/")
        return render(request, "add_class.html")
    
    # CBV版添加装饰器
    from django.views import View
    from django.utils.decorators import method_decorator
    
    第一种:(给各自加)
        class AddClass(View):
    
            @method_decorator(wrapper)
            def get(self, request):
                pass
    
            @method_decorator(wrapper)
            def post(self, request):
                pass
    
    第二种:(给dispatch加)
        class AddClass(View):
    
            @method_decorator(wrapper)
            def dispatch(self, request, *args, **kwargs):
                print('before')
                obj = super(Login,self).dispatch(request, *args, **kwargs)
                print('after')
                return obj
    
            def get(self, request):
                pass
    
            def post(self, request):
                pass
    
    第三种:(给类加)
        @method_decorator(wrapper,name='get')
        @method_decorator(wrapper,name='post')
        class AddClass(View):
    
            def get(self, request):
                pass
    
            def post(self, request):
                pass
    
  • 三、request对象常用属性

    request.method 请求方式 GET POST
    request.GET    字典,URL上传的参数
    request.POST   字典,form表单传的数据
    request.COOKIES.get  获取cookie信息
    request.session.get  获取session信息
    request.is_ajax()  判断请求是不是ajax
    
    request.path_info ---》/add_publisher/ 用户访问的URL,不包括域名
    request.body      ---》一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。
                           但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。
    request.FILES     ---》一个类似于字典的对象,包含所有的上传文件信息。
                            FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
                            注意:FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会
                            包含数据。否则,FILES 将为一个空的类似于字典的对象。
    
    request.get_full_path() -->/test/?id=1  参数也拿到了
    request.path_info       -->/test/       只拿到了url
    
    request.get_host     -->IP+端口  127.0.0.1:8000
    
  • 四、url:路由系统

    (1) urlpatterns = [
                url(正则表达式,views视图,参数,别名)
                ]
    
    (2) ^ 以...为开头,$以...为结尾
    
    (3) 如果项目中没有按照自己以为的去执行函数,可能是因为正则匹配过程中匹配到了别的。
          匹配时从上往下依次匹配,如果上面有符合要求的,就不会走下面的。
          url(r'^book/',)
          url(r'^book/asd')
          一般可写成url(r'^book/$')规定开头结尾,约束
    
    (4)  url位置参数说明:
         # 用户输入url,满足条件匹配上之后,才能将参数传进test函数,让test函数对url中分组内的参数进行处理。
         # 即用户可通过url输入参数,url匹配成功后,通过url进行传参,传括号里的内容传给函数进行处理。
         无名分组:
           实例1:
                用户输入:
                    127.0.0.1:8000/test/2018/08
                url:
                    url(r'^test/([0-9]{4})/[0-9]{2}',views.test)
                函数:
                    def test(request,*args,**kwargs):
                        print(args)
                        输出结果:('2018',)
                        return HttpResponse('你自己输入的{},你还愁啥'.format(args))
                        页面显示:你自己输入的('2018',),你还愁啥
    
            实例2:
                用户输入:
                    127.0.0.1:8000/test/嘀嗒嘀嗒嘀嗒嘀。。。。(随便输入)
                url:
                    url(r'^test/([0-9]{4})/[0-9]{2}',views.test),不走这个
                    url(r'^test/(.+)',views.test1) 走这个
                函数:
                    def test1(request,*args):
                        return HttpResponse(args[0])
                       页面显示:输入什么就显示什么
    
                    url(r'^test/(.{3})',views.test1),这个是不管输入多少,只显示3个字
    
    (5) # 是否开启URL访问地址后面不为/,也能跳转至带有/的路径的配置项:
          配置中写入这个,不加/也能自动添加/再走一次
          APPEND_SLASH=True (默认为True,所以不写也能自动添加)
          如果不想让其自动添加,就改为 False
    
    (6)分组命名匹配:(区别在于:函数中只接收正则中命名的名字作为参数,将匹配到的结果传给函数)
         有名分组:
         实例:
           用户输入:
                  http://127.0.0.1:8000/test/阿斯顿法国红酒看来
           url中:
                  url(r'^test/(?P<nei_rong>.{2})',views.test2)
           views中:
                  def test2(request,nei_rong):
                     print(nei_rong)
                     输出结果:阿斯
                     return HttpResponse('输入的内容为:{}'.format(nei_rong))
                     页面显示:输入的内容为:阿斯
    
    (7) 后端接收到的url中的参数都是字符串!
    
    (8) 视图函数中指定默认值
          # urls.py中
          from django.conf.urls import url
    
          from . import views
    
          urlpatterns = [
                  url(r'^blog/$', views.page),
                  url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
              ]
    
          # views.py中,可以为num指定默认值
          def page(request, num="1"):
               pass
    
    (9) 包含其他的url:(可将不同url写进不同的业务线下,然后用总的包含)
          from django.conf.urls import include, url
          from app01 import urls
    
          urlpatterns = [
             url(r'^admin/', admin.site.urls),
             url(r'^app01/', include('app01.urls')),  # 可以包含其他的URLconfs文件
             【1,不导入,写字符串,反射找到】
    
             from app01 import urls as app01_urls
             url(r'^app01/', include(app01_urls))
             【2,导入,不用写成字符串】
          ]
    
    (10) 当两个app写了两个相同的url,反向解析时就会冲突,所以要将不同的app下的url写不同的标记,即
          在总的url中,命名空间。
          url(r'^app01/', include('app01.urls'),namespace='app01')
          url(r'^app02/', include('app02.urls'),namespace='app02')
    
          反向解析时:
          url = reverse('app01:index')
          url = reverse('app02:index')
    
          起了namespace,都要用app01:加前缀
          url = reverse('app01:book')
    
    (11) url中可传参数(可以在url中自己写一个参数,字典中的,传给views中的相应函数)
          urlpatterns = [
              url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
          ]
    
  • 五、命名url和url的反向解析

    1,起名字:
        url(r'^json/',views.json_data,name='js')
    
    2,用(可在视图中用,可在模板中用)
        视图中用:
            导入reverse:
            from django.shortcuts import render,HttpResponse,reverse
    
            url = reverse('js')
            结果是/json/,即使改为/jsonfgieue/,也能通过js找到。通过名字就能找到这个url,
            比较灵活(不带参数的),通过名字,找到url,字符串类型
    
        模板中用:
            url(r'baidusss/',views.baidu,name='baidu')
            <a href="/baidu/">这是跳转到一个自定义的百度路由(写死的),然后返回一个百度的连接</a>
    
            <a href="{% url 'baidu' %}">这个连接用的是反向解析,如果views中的url变了,上面就找不到了</a>
    
    3,作用:不怕url改名字。不管怎么改,我的模板中,函数中,都能找到此路由,
          这就给自己提供了方便,即使路由改了,html页面中或函数中要跳转的路由不用改,只是用户输入时需要改。
          因为程序内部有这个反向解析的方法能找到,而用户只能是提供什么url就写什么url
    
    4,带参数的用法(无名分组)
            url(r'^testtttttt/([0-9]{4})/([0-9]{2})',views.test,name='test')
    
            视图中,需传参
                url = reverse('test',args=('1998','08))
    
            模板中,需传参
                <a href="{% url 'test' '1998' '08' %}">测试</a>
    
    5,带有名分组的参数
            url(r'^testtttttt/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})',views.test,name='test')
    
            视图中,传位置参数
                url = reverse('test',kwargs={'year':'1998','month':'08'})
    
            模板中,传参
                <a href="{% url 'test' '1998' '08' %}">测试</a> (对应先后顺序)
                或者
                <a href="{% url 'test' month='08' year='1998' %}">测试</a> (可换位置)
    

    举个栗子:

    总路由:
    urlpatterns = [
          url(r'^goods/', include('df_goods.urls', namespace='df_goods')),  # 添加实例命名空间
    ]
    
    子路由:
    urlpatterns = [
        url('^index/$', views.index, name="index"),
    ]
    
    视图应用:
    print(reverse("df_goods:index"))  # 利用reverse函数反向解析url
    # 打印结果为/goods/index/
    
    页面应用:
    <a href="{% url "df_goods:index" %}">反向解析</a>
    
  • 六、session

    Cookie虽然解决了“保持状态”的需求,但是cookie最大支持4096字节,且cookie保存在客户端,可能被拦截或窃取。
    
    因此就需要有一种新的东西,支持更多字节,并且保存在服务器,有较高的安全性,这就是Session。
    
    Session
        1,接收请求,返回响应
        2,返回响应时,生成一个特殊的字符串
        3,在后端开一块空间,保存请求相关数据
        4,返回响应
    
        下一次请求时:
            1,带着之前发给浏览器的字符串
            2,拿着字符串找相应的箱子
            3,在箱子中根据key取值
    
    前提:django存储session是在内置的 django_session 表中,所以必须先生成其表。
    
    1. 设置Session:
        不需要在响应中设置,直接request.session['key']='value'
      
        1. request.session[key] = value
        2. request.session.setdefault(key, value)   --> 有就啥都不干,没有就赋值
    
    2. 获取session:
        if request.session.get('key','')== 'value':
            pass
    
        1. request.session[key]
        2. request.session.get(key)  推荐
    
    3. 删除Session
      1. request.session.delete()
      2. request.session.flush()     --> 删除Cookie和Session
    
    4. 清空已经过期的session数据
        request.session.clear_expired()
    
    5. 设置Session过期时间
        request.session.set_expiry(过期时间)
    
        session中的有效日期,默认是两周
    
    6. settings配置中:
        SESSION_SAVE_EVERY_REQUEST = True
        # 一般设为True
        # 每次请求都更新超时时间,超时时间从最近的一次请求算起。
    
        SESSION_COOKIE_AGE = 129600 --->默认两周
    
  • 七、使用 pymysql 连接 mysql

    1,创建mysql数据库
    2,settings配置:
            DATABASES = {
                    'default': {
                        'ENGINE': 'django.db.backends.mysql',
                        'NAME': 'chubanshe_book',
                        'HOST': '127.0.0.1',
                        'POST': 3306,
                        'USER': 'root',
                        'PASSWORD': '',
                    }
                }
    3,告诉django使用pymysql来连接数据库:
        在与项目同名的文件夹下的__init__.py文件中写:
        import pymysql
        pymysql.install_as_MySQLdb()
    
    4,在app01/models.py写类(必须继承models.Model)
        class Publisher(models.Model):
            id = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32,null=False,unique=True)
    
    5,执行数据库迁移两条命令
        python manage.py makemigrations # 保存models修改记录
        python manage.py migrate   # 操作数据表
    
    
     1         2                3                         4                      5
    创表,  我要连(配置),  我要用什么连(pymysql),  形成映射关系(model),  两条命令
    
  • 八、内置auth认证

    • auth认证:默认django内置的认证系统,默认在数据库使用auth_user表

    • 扩展内置user表

      models.py:
        from django.contrib.auth.models import AbstractUser
        class UserInfo(AbstractUser):
            phone = models.CharField(max_length=11)
      
      settings.py:
        AUTH_USER_MODEL = "app01.UserInfo"
      
      views.py:
         models.UserInfo.objects.create_user(password=pwd,username=user,phone=pho)
      
    • django的登录:auth.login(request,user)

    • django的注销:auth.logout(request)

    • 用户是否登陆:request.user.is_authenticated

    • 验证用户名密码是否正确:auth.authenticate(request, username=username, password=pwd)

    • 登录认证装饰器:login_required
      LOGIN_URL = '/login/' # 配置将内置登录路由替换成自己的登录路由

    • 登录用户显示用户名,非登录用户请登录:user.is_authenticated

    • 检查原密码:check_password(password)---> 修改密码时使用
      auth 提供的一个检查密码是否正确的方法,需要提供当前请求用户的密码。
      密码正确返回True,否则返回False。
      ok = request.user.check_password('密码')

    • 重置新密码:set_password(password)---> 修改密码时使用
      auth 提供的一个修改密码的方法,接收 要设置的新密码 作为参数。
      注意:设置完一定要调用用户对象的save方法!!!
      request.user.set_password(密码)
      request.user.save()

  • 九、模板语法中的for循环

相关文章

  • django里的那些事儿

    一、CBV版视图二、给视图加装饰器三、request对象常用属性四、url:路由系统五、命名url和url的反向解...

  • 汽车销售那些事儿3

    《汽车销售那些事儿》目录 汽车销售那些事儿4 汽车销售那些事儿2 1 蝉鸣的季节里,空气中充满离别的味道。 校园里...

  • 作文里的那些事儿

    都说中学生学语文有三怕,一怕文言文,二怕周树人,三怕写作文。可我认为他们中大多数最怕的是写作文,因为作文要求字数多...

  • 月子里的那些事儿

    如果有人问我老公和孩子谁更重要,我会说老公。同样的道理孩子和产妇谁更重要,当然是产妇。 我先给大家讲一下我的生产经...

  • 婚姻里的那些事儿

    婚姻里的那点事儿 今天闺蜜又来找我诉苦了,想让我撮合她和前夫能再次走到一起。因为实在受不了儿子不在自己身边的感觉,...

  • 日记里的那些事儿

    爱写日记,不知道是从什么时候沾染上这一个习惯。年少轻狂的日子里,全靠一本本日记去回忆,每一本日记里都记录着某个...

  • ICU里的那些事儿

    从实习到现在,我已经在总医院度过了8个年头。寒暑交替间,我见证了新大楼的拔地而起,二次创业的众志成城,三甲评审准备...

  • 庙会里的那些事儿

    终于放假了,放假这件事情我期待好久了,不过,在家好无聊,昨天是最无聊的一天。 昨天脑子里空空空的,连要写作文的事情...

  • 暑期里的那些事儿

    年纪越长,倒越喜欢记个日志,好像指望着用文字去定格定格眉梢,用话语来阻拦阻拦流逝,好像梳理梳理,便把日日夜夜都攥在...

  • 村子里的那些事儿

    之前一直在脑子里面想,构思,想着要把自己的从小生活到大的地方写写,写写那些人和事,写写哪里的一些故事。也给自己记录...

网友评论

      本文标题:django里的那些事儿

      本文链接:https://www.haomeiwen.com/subject/crvnaqtx.html