zoukankan      html  css  js  c++  java
  • VS2019 开发Django(八)------视图

    导航:VS2019开发Django系列

    这几天学习了一下Django的视图和模板,从这几天的学习进度来看,视图这里并没有花很多的时间,相反的,模板花费了大量的时间,主要原因还是因为对Jquery操作dom不熟练,其次就是对bootstrap的使用不熟练,所以花了一些时间研究官方文档。

    那么,言归正传,先从视图(views.py)开始讲起。Django中视图与其他框架中的视图(尤其是MVC模式)不一样,Django中的视图,用Asp.Net Mvc框架来类比的话,就是Controller,里边的视图函数就是Action,这个在第二篇博文中介绍文件目录结构的时候有提到过,那么我们的请求,要到达一个Controller,然后到达一个Action,需要一个路由表,Django中也是有类似的设计的,只是换了个说法,叫做URL调度器,具体的用法我们可以查看官方文档,文档中会介绍很多的匹配规则,复杂的可以使用正则表达式来配置匹配规则,但是经验告诉我,这个路由规则还是尽可能简洁明了的好,因为如果不是开放给第三方的Api的话,用这个规则的终究是自己,反过来,就算是开放给第三方的Api,搞得太复杂也会让人诟病。当然这只是我的个人见解......

    接下来,就到了直接上代码的时候了,看DjangoLazyOrders这个项目中,我的URL配置是怎么配置的:分为两部分,一个是整个应用的URL配置,一个是hello这个App的URL配置,着重看着色部分代码。

    #D:项目localDjangoLazyOrdersDjangoLazyOrdersurls.py
    urlpatterns = [path('', views.home, name='home'),
        path('contact/', views.contact, name='contact'),
        path('about/', views.about, name='about'),
        path('login/',
             LoginView.as_view(template_name='app/login.html',
                 authentication_form=forms.BootstrapAuthenticationForm,
                 extra_context=
                 {
                     'title': 'Log in',
                     'year' : datetime.now().year,
                 }),
             name='login'),
        path('logout/', LogoutView.as_view(next_page='/'), name='logout'),
        path('admin/', admin.site.urls),
        path('hello/', include('hello.urls')),]
    from django.urls import path,include
    from hello import views
    
    #D:项目localDjangoLazyOrdershellourls.py
    urlpatterns = [path('hello/',views.hello,name='hello'),
                   path('test/',views.test,name='test'),
                   path('lazy_orders_index/',views.lazy_orders_index,name='lazy_orders_index'),
                   path('<int:category_id>/category/', include([path('delete/', views.category_delete,name='category_delete'),path('edit/', views.category_edit,name='category_edit')]))]

    那么,以上代码代表的规则是什么呢?

    1)hellourls.py中的配置一共展示了有三个视图,分别是lazy_orders_index,category_delete,category_edit,那么,这三个视图分别对应的视图函数该怎么定义呢?直接看代码(部分代码未实现完整):

    • lazy_orders_index 参数request是必须带的,所有的视图函数第一个参数永远是request,因为第一个路由规则没有配置参数,所以只有这个默认的参数
    • category_delete,category_edity有一个公共部分<int:category_id>,删除和编辑需要提供一个参数category_id,所以把公共部分提取出来放到前面,然后再各自匹配各自的规则,delete与edit
    import json
    from datetime import datetime
    from django.core import serializers
    from django.shortcuts import render
    from django.http import HttpResponse,JsonResponse
    from hello.models import Category,Menu
    
    # Create your views here.
    def hello(request):
        return HttpResponse("hello world!")
    
    def test(request):
        return HttpResponse("test")
    
    def category_edit(request,category_id):
        return HttpResponse("edit")
    
    def lazy_orders_index(request):
        categorys = Category.objects.all()#查询所有的类别
        menus = Menu.objects.all()#查询所有的菜单
    
        json_categorys = []#定义两个数组 用来保存model的json数据
        json_menus = []
    
        for category in categorys:
            json_categorys.append({
            "category_id":category.category_id,
             "category_name":category.category_name#遍历实体对象 构建ViewModel的数据
             })
    
        for menu in menus:
            json_menus.append({
                "category_name":menu.category.category_name,
                "menu_name":menu.menu_name
                })
    
        context = {'json_categorys': json.dumps(json_categorys),'json_menus':json.dumps(json_menus),'categorys':categorys,'menus':menus,'year':datetime.now().year}
        return render(request,'hello/lazyorders.cshtml',context)#将数据和模板传给render函数 渲染成html返回给客户端
    
    def category_delete(request,category_id):
        Category.objects.get(pk=category_id).delete()
        return JsonResponse({'code':0,'message':'ok'})

    2)Django内置的快捷函数

    • render(),将给定的模板与给定的上下文字典组合在一起,并以渲染的文本返回一个 HttpResponse 对象。通俗一点就是将一个request对象,以及指定的模板,和模板中使用到的数据传递给这个函数,函数会将模板渲染成标准的html文本,然后返回给浏览器。
    • redirect(),将一个 HttpResponseRedirect 返回到传递的参数的适当URL。通俗一点就是跳转到指定的URL。

    我们在上面的View中已经使用到了render()函数,模板指定的是hello App下的lazyOrders.cshtml文件(后缀之所以为.cshtml上一篇已经做了解释),数据对象context,context中我既给了直接从数据库中查出来的实体对象,又封装了一个ViewModel的json数据传给了模板,为什么要这么做呢?是因为我要在模板中实现两套逻辑,下一篇模板相关的内容会做详细的介绍,这里只是提一下。

     3)JsonResponse()

    • 要返回Json数据给前端,可以使用HttpResponse,然后指定content-type为application/json即可,示例代码如下:
      def test(request):
          data = {
          'name': 'dengwei',
          'sex': ''
          }
          return HttpResponse(json.dumps(data),content_type="application/json")

    • 除了使用上述方法,Django还提供了一个更方便的http响应类,JsonResponse,查看这个类的源代码可以知道,继承自HttpResponse,并且在内部对数据调用了json.dumps()序列化,同时还发现,这个类要求序列化的对象必须是dict类型对象,如果要序列化非dict的对象,必须传递参数safe为false,默认为true
      class JsonResponse(HttpResponse):
          """
          An HTTP response class that consumes data to be serialized to JSON.
      
          :param data: Data to be dumped into json. By default only ``dict`` objects
            are allowed to be passed due to a security flaw before EcmaScript 5. See
            the ``safe`` parameter for more information.
          :param encoder: Should be a json encoder class. Defaults to
            ``django.core.serializers.json.DjangoJSONEncoder``.
          :param safe: Controls if only ``dict`` objects may be serialized. Defaults
            to ``True``.
          :param json_dumps_params: A dictionary of kwargs passed to json.dumps().
          """
      
          def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                       json_dumps_params=None, **kwargs):
              if safe and not isinstance(data, dict):
                  raise TypeError(
                      'In order to allow non-dict objects to be serialized set the '
                      'safe parameter to False.'
                  )
              if json_dumps_params is None:
                  json_dumps_params = {}
              kwargs.setdefault('content_type', 'application/json')
              data = json.dumps(data, cls=encoder, **json_dumps_params)
              super().__init__(content=data, **kwargs)
    • 针对非dict类型的对象做如下测试: 
      def test(request):
          #data = {
          #'name': 'dengwei',
          #'sex': '男'
          #}
      
          data = [{
          'name': 'dengwei',
          'sex': ''
          },{
          'name': '女帝',
          'sex': ''
          }]
          
          
          return JsonResponse(data)

    • 增加safe参数,赋值为false之后,再次测试,正常返回
      def test(request):
          #data = {
          #'name': 'dengwei',
          #'sex': '男'
          #}
      
          data = [{
          'name': 'dengwei',
          'sex': ''
          },{
          'name': '女帝',
          'sex': ''
          }]
          
          
          return JsonResponse(data,safe=False)

  • 相关阅读:
    Unity中的Path对应各平台中的Path
    C#里的装箱、装箱和值类型、引用类型
    unity3D自适应分辨率
    python中的-m参数
    手动安装python包
    python生成器
    HDU 1312 Red and Black(bfs)
    HDU 2553 N皇后问题(dfs)
    HDU1043 Eight(BFS)
    UVa230 Borrowers (STL)
  • 原文地址:https://www.cnblogs.com/dwBurning/p/Django8.html
Copyright © 2011-2022 走看看