日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

Django,Ajax,Vue实现文章评论功能

發(fā)布時間:2023/12/20 vue 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Django,Ajax,Vue实现文章评论功能 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Django評論

評論復雜的地方在于需要實現(xiàn)點擊提交評論后評論內容需要立刻出現(xiàn)在下面,還要保持頁面位置不變,所以提交后不能整體刷新頁面,因為刷新以后頁面肯定在最上面,而評論一般都在最下面,所以要用到Ajax

整個過程用到了Django,Vue.js,reqwest,REST_framework,ajax

展示評論內容

展示評論內容可以直接用Django從數(shù)據庫中取出數(shù)據,然后在view中渲染到前端,但這里我想用Vue.js,為了減少django的工作量,提高效率吧

// pinglun.js let vue = new Vue({el : "#app",data : {pinglun : [{'評論者':'zhangsan','評論日期':'2019-6-5','評論時間':'17:47:23','評論內容':'hahahha','對應文章_id':'1'},{'評論者':'zhangsan1','評論日期':'2019-6-5','評論時間':'17:48:23','評論內容':'hahffahha','對應文章_id':'1'},],}, }) <!--pinglun.html--> <div id="app"><div class="alert alert-secondary" role="alert" id="pinglunlist"><div v-for="item in pinglun " ><h5>{{ item.評論者 }}</h5><p>{{ item.評論內容 }}</p></div></div> </div>

這樣js中data的數(shù)據就可以渲染到html頁面了,但我們需要從數(shù)據庫中拿到數(shù)據,并且賦值給data中的pinglun,這里需要一個reqwest模塊,需要下載

npm i reqwest

下載之后訪問json文件里面的那個網址,下載壓縮包,解壓后里面有一個reqwest.js文件,要把這個文件引入,就和用Vue要引入Vue.main.js一樣,reqwest可以從一個url請求數(shù)據,并且返回

// 這是官方api reqwest({// 要請求的路徑url: 'path/to/html'// 請求方式, method: 'post'// 請求時要攜帶的數(shù)據, data: { foo: 'bar', baz: 100 }// 成功請求的回調函數(shù), success: function (resp) {// reap中就包含請求來的數(shù)據qwery('#content').html(resp)} }) reqwest({url: 'path/to/html', method: 'get', data: [ { name: 'foo', value: 'bar' }, { name: 'baz', value: 100 } ], success: function (resp) {qwery('#content').html(resp)} })

應為需要有一個請求的url,所以還需要做一個api接口,這里有兩種辦法,一種是用Django提供的HttpResponse和json直接將序列化后的json數(shù)據渲染到頁面,但這樣只能渲染成json類型,并且存在文字編碼的問題,還可以使用django-rest-framework框架,Django REST框架是一個功能強大且靈活的構建Web api工具包

使用 HttpResponse ,不推薦

# urls.py path('api/json',views.injson),# views.py def injson(request):# 這里的info是手寫的假數(shù)據,若使用這種方法可以從數(shù)據庫中獲取相應數(shù)據再用json.dumps序列化info = [{'評論者':'zhangsan','評論日期':'2019-6-5','評論時間':'17:47:23','評論內容':'hahahha','對應文章_id':'1'},{'評論者':'zhangsan1','評論日期':'2019-6-5','評論時間':'17:48:23','評論內容':'hahffahha','對應文章_id':'1'},]return HttpResponse(json.dumps(info))

使用REST框架

先要安裝這個包以及依賴項

pip install djangorestframework pip install markdown # Markdown support for the browsable API. pip install django-filter # Filtering support

其次需要在setting.py中配置app

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','myblog',# 這個就是REST依賴項'rest_framework' ]

然后就要寫api了,先把評論的model放出來

class 評論(models.Model):評論者=models.CharField(max_length=20)評論日期=models.DateField(auto_now_add=True)評論時間=models.TimeField(auto_now_add=True)評論內容=models.TextField()對應文章=models.ForeignKey('myblog.文章內容',on_delete=models.CASCADE)

然后編寫api.py

# api.py# 引入model from .models import 評論 # REST提供的序列化工具 from rest_framework import serializers from rest_framework.response import Response from rest_framework.decorators import api_view

Resonse

類似于HttpResponse,用來渲染文本內容,并根據內容決定返回給用戶的數(shù)據類型

Response(data, status=None, template_name=None, headers=None, content_type=None)# data:要渲染的數(shù)據,可以是python的基本數(shù)據類型 # status:狀態(tài)碼 # template_name:模板名稱 # headers:頭部信息 # content_type:內容類型的響應

因為Response只能渲染python基本數(shù)據類型,對于復雜的數(shù)據類型,需要serializers.ModelSerializer來序列化

# api.pyclass PingLun(serializers.ModelSerializer):class Meta:depth = 1model = 評論fields = ('評論者','評論日期','評論內容')

然后就可以寫url對應的回調函數(shù)了,可以不使用api_view修飾器,但需要自己寫一個判斷來判斷請求的類型

@api_view(['GET']) def showdata(request):id = request.GET['id']print(id)datas=評論.objects.filter(對應文章_id=id)PingLunData = PingLun(datas,many=True)return Response({'data':PingLunData.data})

這時候訪問api就可以看到優(yōu)雅的數(shù)據了,完了以后完善Vue,編寫reqwest的內容

let vue = new Vue({el : "#app",data : {// 開始是一個空列表pinglun : [],},mounted(){console.log("賣個萌咋了!!!(>人<;)")this.getData()},computed : {},methods : {getData : function() {// 現(xiàn)在的this是window對象,等進入reqwest,this就是rewqest對象了,所以提前保存thislet self = this// 只是為了獲取當前文章的idlet myurl = window.location.hreflet id = myurl.toString().split("/").pop()reqwest({url: '/blog/api/showpinglun/?format=json', method: 'get', data: [{name: 'id',value: id}], success: function (data) {self._data.pinglun = data.data}})},} })

到目前,就可以使用Vue從數(shù)據庫中獲取數(shù)據并渲染到前端了,總結一下:

  • 要用Vue渲染數(shù)據,數(shù)據就必須在data中,但我們又不能寫死,必須從一個地方動態(tài)獲取數(shù)據
  • 這個地方就是api,django有一個模塊REST專門用來建立api
  • 要動態(tài)請求數(shù)據,需要用到一個框架 reqwest
  • REST渲染數(shù)據用到了Resonse,但它只能渲染python基本數(shù)據,從Object.filter()得到的顯然不是,因此還要序列化數(shù)據,這里用到了serializers
  • 另外,還需要api_view這個裝飾器判斷請求類型
  • 提交評論

    思路:

  • 使用POST請求
  • 把表單內容交給api,api再保存到數(shù)據庫
  • 看著挺簡單,但這里面有兩個問題:

  • Django要求所有POST請求進行CSRF驗證,使用正常的表單我們可以添加{{csrf_token}},Django會自動在Cookies中添加csrf驗證用的隨機序列,用reqwest怎么辦
  • 一般情況下提交評論后評論會立刻顯示在下面,怎么做
  • 解決Ajax發(fā)送POST請求的CSRF問題

    這里有兩種思路

    思路一:解決發(fā)現(xiàn)問題的人

    這種思路簡單粗暴,既然問題出在了csrf驗證上,那就不讓他進行驗證就好了嘛,組織進行驗證有兩個簡單的辦法

    使用裝飾器

    在要取消進行csrf驗證的視圖函數(shù)上添加修飾器@csrf_exempt

    from django.views.decorators.csrf import csrf_exempt @csrf_exempt def demo(request):pass
    趕盡殺絕法

    第二種是狼人的做法,比較絕,直接從setting中刪除csrf驗證的依賴項

    MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware',# 就是這個,刪了就ok,但安全性嘛,就。。。。'django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware', ]

    思路二:釜底抽薪

    思路一實現(xiàn)簡單,一勞永逸,看似不錯,但取消csrf驗證會讓網站處于很危險的境地,建議不要這樣用,第二種方法就要優(yōu)雅很多,首先要知道Django是怎樣防御CSRF攻擊的,CSRF,跨站請求偽造攻擊,是攻擊者利用用戶登錄保存的cookies偽裝成用戶進行非發(fā)操作的攻擊方式,比如攻擊者在某網站留下了一個付款的鏈接www.xxxx.com/shop?money=500;to=hark(注意,這個鏈接已經設計了用戶驗證,只有正確登錄后才能付款,沒登錄直接訪問這個鏈接會被重定向到登錄界面),一個受害者在訪問這個釣魚鏈接之前正好訪問過付款的那個網站,并登錄留下了自己的cookies,這時候她再去訪問那個釣魚鏈接,瀏覽器就會檢查本地有沒有對應的cookies文件,正好有,系統(tǒng)就認為是他本人在付款,這就是一次csrf攻擊,csrf的特點是攻擊者并沒有拿到受害人的cookies,針對這個特點,django的處理辦法是在cookies中增加一個csrf_token字段,內容為隨機序列,同時表單提交時也把這個序列作為表單的一項同表單數(shù)據一起提交給后端做驗證,如果表單中的序列與cookies中的序列不一樣,就定義為csrf攻擊,在Debug模式下會拋出403錯誤。

    根據這個,我們只要在Ajax的請求頭中加上cookies中的那個字段就可以了嘛,其實如果不懂csrf,直接在瀏覽器開發(fā)者工具里對比我們的Ajax請求頭和正常的POST請求頭就會發(fā)現(xiàn)我們少了X-CSRFToken這個字段,獲取本站cookies中的csrftoken字段,添加到請求頭中就可以。其實對比發(fā)現(xiàn)我們還缺了一項,不寫會報500錯誤,Content-Type

    setRequestHeader必須寫在open之后
    // js獲取cookies依賴下面的庫 <script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>// 獲取cookies let csrftoken = Cookies.get('csrftoken');// 設置請求頭 XHRObject.setRequestHeader("X-CSRFToken", csrftoken);

    Ajax發(fā)送POST請求

    <div id="app"><div class="alert alert-primary" role="alert"><p>評論<<</p><hr /><div class="form-group"><label for="exampleFormControlInput1">評論者:</label><input type="text" class="form-control" id="exampleFormControlInput1" placeholder="請輸入你的姓名" name="評論者" maxlength="20" required=""></div><div class="form-group"><label for="exampleFormControlTextarea1">有問題?不妨寫下了...</label><textarea class="form-control" name="評論內容" id="exampleFormControlTextarea1" rows="3"></textarea></div><hr><button type="submit" name="評論提交" οnclick="XMLDoc()"">提交評論</button></div> function XMLDoc(){let XHRObject// 適配瀏覽器if(window.XMLHttpRequest){XHRObject = new XMLHttpRequest}else{XHRObject =new ActiveXObject("Microsoft.XMLHTTP")}// 接收XHRObject.onreadystatechange = function () {if (XHRObject.status == 200 & XHRObject.readyState == 4) {}}// 獲取文章idlet url = window.location.hreflet id = url.toString().split("/").pop()// 獲取csrftokenlet csrftoken = Cookies.get('csrftoken');// 獲取表單數(shù)據let name = document.getElementById('exampleFormControlInput1').valuelet neirong = document.getElementById('exampleFormControlTextarea1').value// 發(fā)送POST請求XHRObject.open("POST","/blog/api/postpinglun/?format=json",true)// 設置請求頭XHRObject.setRequestHeader("X-CSRFToken", csrftoken);XHRObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");// 發(fā)送請求,只接受一個字符串,鍵值用=連接,多個鍵值對用&連接XHRObject.send('name='+name+'&neirong='+neirong+'&id='+id.toString())document.getElementById('exampleFormControlInput1').value = ""document.getElementById('exampleFormControlTextarea1').value = ""}

    api保存數(shù)據到數(shù)據庫

    @api_view(['POST']) def postdata(request):# 獲取Ajax傳來的表單信息name = request.POST['name']neirong = request.POST['neirong']id = request.POST['id']# 保存到數(shù)據庫obj=評論(評論者 = name,評論日期 = datetime.datetime.now().strftime('%Y-%m-%d'),評論時間 = datetime.datetime.now().strftime('%H:%M:%S'),評論內容 = neirong,對應文章_id = id)obj.save()

    提交數(shù)據時更新下方評論列表

    要在提交時更新,就要綁定兩個單擊事件,一個是Ajax的,用來保存數(shù)據,另一個是Vue的,用來更新數(shù)據,這里可以直接調用之前的getData函數(shù)

    <button type="submit" name="評論提交" onclick="XMLDoc()" @click="getData()">提交評論</button>

    總結

    以上是生活随笔為你收集整理的Django,Ajax,Vue实现文章评论功能的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。