內容回顧
1. BBS項目 CMS
1. 登陸
1. form組件
2. auth模塊
3. 驗證碼
2. 註冊
1. form組件
1. 生成html代碼
直接for循環form_obj,就可以遍歷全部字段
2. 驗證
1. 默認的那些驗證
2. 正則的驗證
3. 全局鉤子作確認密碼的驗證
4. 判斷用戶名是否已經存在
1. input框失去焦點就發ajax到後端判斷
2. form組件中使用局部鉤子來判斷
2. auth模塊 --> 擴展auth_user表 --> create_user()
1. UserInfo這個類裏面,avatar是一個FileField
avatar = models.FileField(upload_to="avatars/", default="avatars/default.png")
2. 注意事項:
1. FileField保存的是一個路徑,而不是一個文件
2. upload_to:具體保存的文件路徑就會在media目錄下
3. 上傳頭像
1. ajax如何上傳文件
2. Django中media的配置
1. settings.py中:
- MEDIA_URL:別名
- MEDIA_ROOT:給用戶上傳的全部文件指定一個存放目錄
2. urls.py中:
from django.views.static import serve
from django.conf import settings
url(r'^media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT})
3. 博客首頁
1. 文章列表(排樣式)
2. 分頁
1. 封裝的要完全
2. 封裝後的結果要有普適性(url要寫成配置項)
4. 我的博客主頁
1. 分類
1. 文章分類
2. 文章標籤
2. 日期歸檔
1. 日期格式化函數 --> MySQL內置的函數都有哪一些? --> 《漫畫數據庫》
1. MySQL:DATE_FORMAT('字段', '格式')
2. sqlite:strftime('格式', '字段')
2. ORM中如何執行原生的SQL語句
1. 使用extra()在執行ORM查詢的同時,嵌入一些SQL語句
2. 直接執行原生SQL語句
from django.db import connection
cursor = connection.cursor()
cursor.execute('select id from userinfo;')
cursor.fetchall()
3. 分組聚合
QuertySet.annotate() --> 分組,前面查的是什麼字段就按什麼字段分組
QuertySet.aggregate() --> 聚合,給QuerySet中的每一個對象多一個屬性
4. 4合1路由
不一樣的路由可使用同一個視圖函數!!! --> 視圖函數中經過參數的不一樣,實現不一樣的功能
5. 文章詳情頁
1. 母板繼承
2. inclusion_tag
1. 返回一段HTML代碼,用數據填充的HTML代碼
2. 具體的寫法
1. 在app下面建立一個名爲 templatetags 的 Python Package
2. 在上面的包中建立一個 py文件
3. 按照inclusion_tag的格式要求寫功能函數
from django import template
register = template.Library()
@register.inclusion_tag(file='xx.html')
def show_menu(*arg):
...
return {"k1": "v1"}
(xx.html中使用k1這個變量)
3. 點贊
1. ajax發送點讚的請求
1. 點贊必須是登陸用戶,沒登陸跳轉到登陸頁面
2. 不能給本身的文章點贊
3. 一個用戶只能給一篇文章點一次贊或踩一次
2. 後端建立點贊記錄(事務操做)
1. 建立新的點贊記錄
2. 去對應的文章表裏把點贊數更新一個
3. ORM事務操做
from django.db import transaction
with transaction.atomic():
sql1;
sql2;
4. Django模板語言裏面的JS代碼
如何在js中引用模板語言的變量,注意加引號!!!
html
接下來就開始寫評論區的功能了,首先就是在頁面佈局:jquery
咱們但願吧頁面佈局成這個樣式:ajax
在bootstrap找到樣式以後,做相應的改動:咱們先想一下,在這個區域須要哪些數據,首先就是評論發表的時間,評論的做者,還有評論的內容。因此在文章詳情頁面的試圖函數中應該傳一些comment的參數。以後再頁面中,經過for循環,逐個展現評論:sql
<!--評論展現區 開始--> <h4>評論</h4> <div class="list-group comment-list"> {% for comment in comment_list %} <div href="#" class="list-group-item"> <h4 class="list-group-item-heading comment-header"> <span>#{{ forloop.counter }}樓</span> <span>{{ comment.create_time|date:'Y-m-d H:i' }}</span> <span>{{ comment.user.username }}</span> <span></span> </h4> <p class="list-group-item-text">{{ comment.content }}</p> </div> {% endfor %} </div> <!--評論展現區 結束-->
接下來就是發表評論的區域了:數據庫
一樣是先佈局,而後html代碼:django
<!--發表評論區 開始--> <h4>發表評論</h4> <div>暱稱: <input type="text"value="{{ request.user.username }}" disabled> </div> <div> <p>評論內容:</p> <textarea cols="60" rows="10"></textarea> </div> <div> <button class="btn btn-success">提交</button> </div> <!--發表評論區 結束-->
接下來就是發送ajax請求了。bootstrap
咱們可以很容易的寫出來這步:後端
//給評論按鈕綁定點擊事件 $('#submit-comment').click(function () { var userid = '{{ request.user.id }}'; var articleid = '{{ article_obj.id }}'; var content = $('#new-comment').val(); var csrf_token = $('[name="csrfmiddlewaretoken"]').val(); $.ajax({ url:'/comment/', type:'post', data:{ user_id:userid, article_id:articleid, content:content, csrfmiddlewaretoken:csrf_token, }, success:function (res) { console.log(res) } }) })
試圖函數也能夠這樣寫;
def comment(request): if request.method == 'POST': res = {'code':0} user_id = request.POST.get('user_id') article_id = request.POST.get('article_id') content = request.POST.get('content')
with transaction.atomic():
# 1.先去建立新評論
comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content)
# 2.再去更新該文章的評論數
models.Article.objects.update(comment_count=F('comment_count')+1)
return JsonResponse(res)
這樣基本的評論功能已經寫出來了,給文章評論以後,刷新以後在頁面上就可以展現出評論內容,app
可是咱們實際的評論不是這樣的,當咱們評論以後,評論內容就會立刻出如今展現區,不用經過刷新。這一步怎麼實現呢?函數
這就要求咱們在發送請求成功以後的success函數中將它經過js操做展現出來,說白了就是在原來評論展現區的下面再添加一個展現區。因此試圖函數要返回一些數據:
views.py代碼:
def comment(request): if request.method == 'POST': res = {'code':0} user_id = request.POST.get('user_id') article_id = request.POST.get('article_id') content = request.POST.get('content')
with transaction.atomic():
# 1.先去建立新評論
comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content)
# 2.再去更新該文章的評論數
models.Article.objects.update(comment_count=F('comment_count')+1)
res['data'] = {
'id':comment_obj.id,
'username':comment_obj.user.username,
'content':comment_obj.content,
'create_time':comment_obj.create_time.strftime("Y-m-d") # 這部若是看不懂的話就去複習一下那三種時間格式的相互轉化 }
return JsonResponse(res)
在說js操做代碼以前,咱們先來複習一個知識:就是js中的字符串格式化輸出。
# 給評論按鈕綁定點擊事件
$('#submit-comment').click(function () { var userid = '{{ request.user.id }}'; var articleid = '{{ article_obj.id }}'; var content = $('#new-comment').val(); var csrf_token = $('[name="csrfmiddlewaretoken"]').val(); $.ajax({ url:'/comment/', type:'post', data:{ user_id:userid, article_id:articleid, content:content, csrfmiddlewaretoken:csrf_token, }, success:function (res) { console.log(res) if(res.code===0){ var data = res.data //先計算原來.comment-list的後代有幾個div,即有幾我的評論,而後再加一 var num = $('.comment-list>div').length + 1; //建立評論成功後,經過js在評論區列表在添加一條評論 var commenthtml = ` <div href="#" class="list-group-item"> <h4 class="list-group-item-heading comment-header"> <span>#${ num }樓</span> <span>${ data.create_time }</span> <span>${ data.username }</span> <span></span> </h4> <p class="list-group-item-text">${ data.content }</p> </div> ` //在原來的評論列表後面添加一條 $('.comment-list').append(commenthtml) //情空 textarea $('#new-comment').val('') } } }) })
上面寫的是添加父評論。
接下來添加子評論,就是回覆的部分了:
博客園中當咱們點擊回覆按鈕時,評論區會顯示這樣:
分爲兩部:當咱們點擊回覆標籤時,光標就會聚焦在評論區,而且出現了@xxx
這個如何實現呢?
$('.replay').click(function () { //光標聚焦在textarea //出現@xxx var replayname = $(this).prev().text() //取到當前標籤的前一個標籤的文本 $('#new-comment').focus().val('@'+replayname+'\n') })
comment表裏有parent_comment字段,咱們應該怎麼取到這個字段的id呢?
當咱們點擊提交的時候,咱們無論有沒有父評論都給後端傳一個parent_id,咱們給評論的那個div加一個自定義的id
<div href="#" class="list-group-item" my_id="{{ comment.id }}">
<!--評論展現區 開始--> <h4>評論</h4> <div class="list-group comment-list"> {% for comment in comment_list %} <div href="#" class="list-group-item" my_id="{{ comment.id }}"> <h4 class="list-group-item-heading comment-header"> <span>#{{ forloop.counter }}樓</span> <span>{{ comment.create_time|date:'Y-m-d H:i' }}</span> <span>{{ comment.user.username }}</span> <span></span> </h4>
{% if comment.parent_comment %}
<span style="display: block">@{{ comment.parent_comment.user.username }}</span>
<p class="list-group-item-text well">
{{ comment.parent_comment.content }}
</p>
{% endif %} <p class="list-group-item-text">{{ comment.content }}</p> </div> {% endfor %} </div> <!--評論展現區 結束-->
那麼咱們如何區分誰是父評論誰是子評論呢?當咱們點擊回覆的時候,產生的評論就是子評論,直接點擊提交就是父評論,那咱們應該怎麼操做呢?
咱們把這個自定義的id添加到提交的按鈕上,當咱們點擊提交的按鈕是進行判斷,若是這個id存在,就說明是子評論,不然就是父評論。
//點擊回覆按鈕時的綁定事件
$('.replay').click(function () { //光標聚焦在textarea //出現@xxx var replayname = $(this).prev().text() ;//取到當前標籤的前一個標籤的文本 $('#new-comment').focus().val('@'+replayname+'\n'); //把當前評論的id值,存到提交的按鈕中 var pID = $(this).parent().parent().attr('my-id'); $('#submit-comment').data('pid',pID) })
//給評論按鈕綁定點擊事件 $('#submit-comment').click(function () { var userid = '{{ request.user.id }}'; var articleid = '{{ article_obj.id }}'; var content = $('#new-comment').val(); var csrf_token = $('[name="csrfmiddlewaretoken"]').val(); var parentId = $(this).data('pid') || ''; if(parentId){
//由於在添加自評論時,會出現@xxx的東西因此咱們按照索引把他去除 content = content.slice(content.indexOf('\n')+1,); } $.ajax({ url:'/comment/', type:'post', data:{ parent_id:parentId, user_id:userid, article_id:articleid, content:content, csrfmiddlewaretoken:csrf_token, }, success:function (res) { console.log(res) if(res.code===0){ var data = res.data //先計算原來.comment-list的後代有幾個div,即有幾我的評論,而後再加一 var num = $('.comment-list>div').length + 1; //建立評論成功後,經過js在評論區列表在添加一條評論 var commenthtml = ` <div href="#" class="list-group-item"> <h4 class="list-group-item-heading comment-header"> <span>#${ num }樓</span> <span>${ data.create_time }</span> <span>${ data.username }</span> <span></span> </h4> <p class="list-group-item-text">${ data.content }</p> </div> `; //在原來的評論列表後面添加一條 $('.comment-list').append(commenthtml); //情空 textarea $('#new-comment').val('');
//當咱們點擊提交按鈕時,應該把自定義的id去掉,否則下一次點擊提交的時候,仍是有這個id值 $("#submit-comment").removeData("pid"); } } }) });
咱們後端也能拿到parent_id。
def comment(request): if request.method == 'POST': res = {'code':0} user_id = request.POST.get('user_id') article_id = request.POST.get('article_id') content = request.POST.get('content') parent_id = request.POST.get("parent_id") #建立評論 with transaction.atomic(): # 1.先去建立新評論 if parent_id: #添加自評論 comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,parent_comment_id=parent_id) else: #添加父評論 comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content) # 2.再去更新該文章的評論數 models.Article.objects.update(comment_count=F('comment_count')+1) res['data'] = { 'parent_id':parent_id, 'id':comment_obj.id, 'username':comment_obj.user.username, 'content':comment_obj.content, 'create_time':comment_obj.create_time.strftime("Y-m-d") } return JsonResponse(res)
這樣添加的評論還不夠完美,就是添加的評論沒有回覆這個功能,
//給評論按鈕綁定點擊事件 $('#submit-comment').click(function () { var userid = '{{ request.user.id }}'; var articleid = '{{ article_obj.id }}'; var content = $('#new-comment').val(); var csrf_token = $('[name="csrfmiddlewaretoken"]').val(); var parentId = $(this).data('pid') || ''; if(parentId){ //由於在添加自評論時,會出現@xxx的東西因此咱們按照索引把他去除 content = content.slice(content.indexOf('\n')+1,); } $.ajax({ url:'/comment/', type:'post', data:{ parent_id:parentId, user_id:userid, article_id:articleid, content:content, csrfmiddlewaretoken:csrf_token, }, success:function (res) { console.log(res) if(res.code===0){ var data = res.data //先計算原來.comment-list的後代有幾個div,即有幾我的評論,而後再加一 var num = $('.comment-list>div').length + 1; //建立評論成功後,經過js在評論區列表在添加一條評論 var commenthtml = ` <div href="#" class="list-group-item"> <h4 class="list-group-item-heading comment-header"> <span>#${ num }樓</span> <span>${ data.create_time }</span> <span>${ data.username }</span> <span class="pull-right replay">回覆</span> </h4> <p class="list-group-item-text">${ data.content }</p> </div> `; //在原來的評論列表後面添加一條 $('.comment-list').append(commenthtml); //情空 textarea $('#new-comment').val(''); //當咱們點擊提交按鈕時,應該把自定義的id去掉,否則下一次點擊提交的時候,仍是有這個id值 $("#submit-comment").removeData("pid"); } } }) });
添加回復這個按鈕後,不能實現點擊,這就用到了事件委託,當一個事件不能完成時,咱們把它委託給他的父標籤作未來的動做。
//給回覆按鈕綁定事件 //$('.replay').click(function () { //事件委託, $('.comment-list').on('click','.replay',function () { //光標聚焦在textarea //出現@xxx var replayname = $(this).prev().text() ;//取到當前標籤的前一個標籤的文本 $('#new-comment').focus().val('@'+replayname+'\n'); //把當前評論的id值,存到提交的按鈕中 var pID = $(this).parent().parent().attr('my-id'); $('#submit-comment').data('pid',pID) })
這就是完整的代碼了
不懂得地方看視頻,(看視頻day79. 004)
上面設計到的知識點,jquery中的data方法,就是咱們能夠給任意一個jQuery對象添加一個值。
js中的三元運算:
還有就是事件委託