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:\項目\local\DjangoLazyOrders\DjangoLazyOrders\urls.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:\項目\local\DjangoLazyOrders\hello\urls.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)hello\urls.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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM