博客系統項目整理:css
一:建立表:html
models代碼:前端
from django.db import models from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): '''用戶信息表''' nid = models.AutoField(primary_key=True) nickname = models.CharField(max_length=32,verbose_name="暱稱",unique=True,null=True,blank=True) tel = models.CharField(max_length=11, verbose_name='電話',unique=True, null=True,blank=True) avatar = models.FileField(verbose_name="頭像",upload_to="avatar",default="/avatar/default.png") create_time = models.DateTimeField(verbose_name="建立時間",auto_now_add=True) class Meta: verbose_name_plural = "用戶信息表" def __str__(self): return self.username class Article(models.Model): ''' 文章表 ''' title = models.CharField(max_length=64,verbose_name="文章標題") summary = models.CharField(max_length=244, verbose_name="文章概要") create_time = models.DateTimeField(verbose_name="建立時間",auto_now_add=True) update_time = models.DateTimeField(verbose_name="修改時間",auto_now=True) poll_count = models.IntegerField(verbose_name="點贊數",default=0) comment_count = models.IntegerField(verbose_name="評論數",default=0) read_count = models.IntegerField(verbose_name="閱讀數",default=0) # is_essence = models.BooleanField(verbose_name="是否精華",default=0) # is_top = models.BooleanField(verbose_name="是否置頂",default=0) user = models.ForeignKey(to="UserInfo",verbose_name="所屬做者",null=True,blank=True) classify = models.ForeignKey(to="Classfication",verbose_name="所屬類別",null=True,blank=True) tags = models.ManyToManyField(to="Tag",through="Article2tag",through_fields=('article', 'tag'),verbose_name="所屬標籤") site_article_category = models.ForeignKey(to="SiteArticleCategory", null=True,verbose_name="文章分類") class Meta: verbose_name_plural = "文章表" def __str__(self): return self.title class Article_detail(models.Model): '''文章細節表''' article = models.OneToOneField(to="Article",verbose_name="所屬文章") content = models.TextField(verbose_name="文章內容") class Meta: verbose_name_plural = "文章細節表" class Tag(models.Model): '''標籤表''' name = models.CharField(max_length=32,verbose_name="標籤名") blog = models.ForeignKey(to="Blog",verbose_name="所屬博客") def __str__(self): return self.name class Meta: verbose_name_plural = "標籤表" class Article2tag(models.Model): article = models.ForeignKey(verbose_name="文章",to="Article") tag = models.ForeignKey(verbose_name="標籤",to="Tag") class Meta: '''聯合惟一''' unique_together = [ ("article","tag") ] class Comment(models.Model): '''評論表''' time = models.DateTimeField(verbose_name="評論時間",auto_now_add=True) content = models.CharField(max_length=265,verbose_name="評論內容") up_count = models.IntegerField(default=0) user = models.ForeignKey(to="UserInfo",verbose_name="評論人",null=True,blank=True) article = models.ForeignKey(to="Article",verbose_name="評論文章",null=True,blank=True) farther_comment = models.ForeignKey(to="Comment",verbose_name="父級評論",null=True,blank=True) # farther_comment = models.ForeignKey("self",verbose_name="父級評論",null=True,blank=True) class Meta: verbose_name_plural = "評論表" class Article_poll(models.Model): '''文章點贊表''' time = models.DateTimeField(verbose_name="點贊時間",auto_now_add=True) article = models.ForeignKey(to="Article",verbose_name="點贊文章",null=True,blank=True) #一個文章能夠有多個贊 user = models.ForeignKey(to="UserInfo",verbose_name="點贊人",null=True,blank=True) # is_positive = models.BooleanField(default=1,verbose_name="點贊或踩") class Meta: '''聯合惟一''' unique_together = ("user", "article",) verbose_name_plural = "文章點贊表" class Comment_poll(models.Model): '''評論點贊表''' time=models.DateTimeField(verbose_name="點贊時間",auto_now_add=True) # is_positive = models.BooleanField(verbose_name="點贊或踩",default=1) user = models.ForeignKey(to="UserInfo",verbose_name="點贊用戶",null=True,blank=True) comment = models.ForeignKey(to="Comment",verbose_name="點贊所屬評論",null=True,blank=True) #一個評論能夠有多個贊 class Meta: '''聯合惟一''' unique_together = ("user","comment",) verbose_name_plural = "評論點贊表" class Blog(models.Model): '''我的站點表''' title = models.CharField(max_length=32,verbose_name="我的博客標題") url = models.CharField(max_length=64,verbose_name="路徑",unique=True) theme = models.CharField(max_length=32,verbose_name="博客主題") user = models.OneToOneField(to="UserInfo", verbose_name="所屬用戶") class Meta: verbose_name_plural = "我的站點表Blog" def __str__(self): return self.title class Classfication(models.Model): '''博主我的文章分類表''' title = models.CharField(max_length=32, verbose_name="分類標題") blog = models.ForeignKey(to="Blog",verbose_name="所屬博客") def __str__(self): return self.title class Meta: verbose_name_plural = "分類表" #與文章表關聯,屬於博客全局的分類 class SiteCategory(models.Model): """ 博客主頁分類,父 """ name=models.CharField(max_length=32) def __str__(self): return self.name class Meta: verbose_name_plural = "博客主頁分類,父" class SiteArticleCategory(models.Model): """ 博客主頁分類,子 """ name=models.CharField(max_length=32) site_category=models.ForeignKey("SiteCategory") def __str__(self): return self.name class Meta: verbose_name_plural = "博客主頁分類,子"
admin:python
from django.contrib import admin # Register your models here. from . import models admin.site.register(models.UserInfo) admin.site.register(models.Article) admin.site.register(models.Article_detail) admin.site.register(models.Tag) admin.site.register(models.Article2tag) admin.site.register(models.Comment) admin.site.register(models.Article_poll) admin.site.register(models.Comment_poll) admin.site.register(models.Blog) admin.site.register(models.Classfication) admin.site.register(models.SiteCategory) admin.site.register(models.SiteArticleCategory)
配置---引用:jquery
#配置 settings: AUTH_USER_MODEL = "app01.UserInfo" #引用from django.contrib.auth.models import AbstractUser from django.db import models from django.conf import settings from django.contrib.auth.models import AbstractUser
表關係:git
博客系統表關係整理; 1:建立用戶信息表(UserInfo):-----------繼承了AbstractUser(配置 settings: AUTH_USER_MODEL = "app01.UserInfo") ----------(from django.contrib.auth.models import AbstractUser) 主鍵(ID) 暱稱(nickname) 電話(tel) 郵箱(email) 頭像(avatar) 建立時間(create_time) 2:建立文章表(Acticle) 文章標題(title) 文章概要(summary) 建立時間(create_time) 修改時間(updata_time) 點贊數(poll_count) 評論數(comment_count) 閱讀數(read_count) 做者(user)-------------------------------與信息表(Userinfo)是一對多的關係 所屬類別(classify)-----------------------與分類表(Classify)是一對多的關係 標籤(tag)--------------------------------與標籤表(Tag)是多對多的關係,過濾關係,一篇文章只能有一層與標籤的關係,不可重複。 博客的類,固定字段只有選擇的權限(type_choices) 3文章詳細表(Article_detail) 所屬文章(article)------------------------與文章表是(Article)是一對一的關係 文章內容(content) 4標籤表(Tag) 標籤名(name) 所屬博客(blog)----------------------------與博客表是一對多的關係 5博客和標籤的關係表(Article2tag)--------------本身建立方便後面添加字段 文章(article)-----------------------------與文章表(Article)是多對一的關係 標籤(tag)---------------------------------與標籤表(Tag)是多對一的關係 6:評論表 評論時間(time) 評論內容(content) 評論人(user)------------------------------與用戶信息表(UserInfo)是多對一的關係 評論文章(article)-------------------------與文章表(Acticle)是多對一的關係 父級評論(father_comment)------------------自關聯(能夠評論別人的評論) 7:文章點贊表(Article_poll) 點贊時間(time) 點贊文章(article)-------------------------與文章表(Acticle)是多對一的關係 點贊人(user)------------------------------與用戶表(UserInfo)是多對一的關係 8:評論點贊表(Comment_poll) 點贊時間(time) 點贊用戶(user)----------------------------與用戶信息表(UserInfo)是多對一的關係 點贊所屬評論(comment)---------------------與評論表(Comment)是多對一的關係 9:博客表(Blog) 我的博客標題(title) 路徑(url) theme(博客主題) user(所屬用戶)----------------------------與用戶信息表是(UserInfo)是一對一的關係 10:博主我的文章分類表(Classfication) 分類標題(title) 所屬博客(blog)----------------------------與博客表是(Blog)是多對一的關係
二:登陸:ajax
界面顯示數據庫
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale"> <title>博客系統首頁</title> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <style> .hides{ display: none; } </style> </head> <body> <nav class="navbar navbar-inverse primary"> <div class="container"> <a class="navbar-brand" href="#">博客園</a> <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse"> <ul class="nav navbar-nav navbar-right"> {% if request.user.is_authenticated %} <li><a href="">{{request.userinfo.uaername}}<span class="glyphicon glyphicon-user"></span></a></li> <li><a href="/log_out/">註銷</a></li> <li><a href="/#/">修改密碼</a></li> {% else %} <li><a href="/login/">登陸</a></li> <li><a href="/register/">註冊</a></li> {% endif %} </ul> <form class="navbar-form navbar-right"> <input type="text" class="form-control" placeholder="搜索"> </form> </div> </div> </nav> <div class="container"> <div class="row col-md-3"> <div class="panel panel-primary"> <div class="panel-body"> 網站分類 </div> <div class="panel-footer"> {% for site in site_list %} <div class="panel panel-primary"> <div class="panel-heading cate_title">{{site.name}}</div> <div class="panel-body hides"> {% for sitearticlecategory in site.sitearticlecategory_set.all %} <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p> {% endfor %} </div> </div> {% endfor %} </div> </div> </div> <div class="col-md-6"> <div class=" article_list"> {% for article in article_list %} <div><a href="">{{article.title}}</a></div> <div class="row"> <div class="avatar col-md-2"> <a href="{% url 'aaa' article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a> </div> <div class="summary col-md-10" > <p>{{article.summary}}</p> </div> </div> <div class="article_info row">   <a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a>   發佈與:{{article.create_time|date:"Y-m-d H:i"}}   <a href=""><span class="glyphicon glyphicon-comment"></span>評論({{article.comment_count}})</a>   <a href=""><span class="glyphicon glyphicon-thumbs-up"></span>點贊({{article.poll_count}})</a>   <a href=""><span class="glyphicon glyphicon-share-alt"></span>閱讀({{article.read_count}})</a> </div> <hr> {% endfor %} </div> </div> <div class="col-md-3"> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> </div> </div> <script> $(".cate_title").mouseover(function () { $(this).next().slideDown(300) }).parent().mouseleave(function () { $(this).children(".panel-footer").slideUp(300) }); {# $(".cate_title").mouseenter(function () {#} {# $(this).next().slideDown(300)#} {# });#} {# $(".panel-footer").mouseleave(function () {#} {# $(this).next().slideUp(300)#} {# });#} </script> </b
導入:django
urljson
url(r'^get_authCode_img/', views.get_authCode_img), url(r'^login/$',views.login),
前端頁面的實現:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale"> <title>博客系統首頁</title> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <style> .hides{ display: none; } </style> </head> <body> <nav class="navbar navbar-inverse primary"> <div class="container"> <a class="navbar-brand" href="#">博客園</a> <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse"> <ul class="nav navbar-nav navbar-right"> {% if request.user.is_authenticated %} <li><a href="">{{request.userinfo.uaername}}<span class="glyphicon glyphicon-user"></span></a></li> <li><a href="/log_out/">註銷</a></li> <li><a href="/#/">修改密碼</a></li> {% else %} <li><a href="/login/">登陸</a></li> <li><a href="/register/">註冊</a></li> {% endif %} </ul> <form class="navbar-form navbar-right"> <input type="text" class="form-control" placeholder="搜索"> </form> </div> </div> </nav> <div class="container"> <div class="row col-md-3"> <div class="panel panel-primary"> <div class="panel-body"> 網站分類 </div> <div class="panel-footer"> {% for site in site_list %} <div class="panel panel-primary"> <div class="panel-heading cate_title">{{site.name}}</div> <div class="panel-body hides"> {% for sitearticlecategory in site.sitearticlecategory_set.all %} <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p> {% endfor %} </div> </div> {% endfor %} </div> </div> </div> <div class="col-md-6"> <div class=" article_list"> {% for article in article_list %} <div><a href="">{{article.title}}</a></div> <div class="row"> <div class="avatar col-md-2"> <a href="{% url 'aaa' article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a> </div> <div class="summary col-md-10" > <p>{{article.summary}}</p> </div> </div> <div class="article_info row">   <a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a>   發佈與:{{article.create_time|date:"Y-m-d H:i"}}   <a href=""><span class="glyphicon glyphicon-comment"></span>評論({{article.comment_count}})</a>   <a href=""><span class="glyphicon glyphicon-thumbs-up"></span>點贊({{article.poll_count}})</a>   <a href=""><span class="glyphicon glyphicon-share-alt"></span>閱讀({{article.read_count}})</a> </div> <hr> {% endfor %} </div> </div> <div class="col-md-3"> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> </div> </div> <script> $(".cate_title").mouseover(function () { $(this).next().slideDown(300) }).parent().mouseleave(function () { $(this).children(".panel-footer").slideUp(300) }); {# $(".cate_title").mouseenter(function () {#} {# $(this).next().slideDown(300)#} {# });#} {# $(".panel-footer").mouseleave(function () {#} {# $(this).next().slideUp(300)#} {# });#} </script> </body> </
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>用戶登陸頁面</title> <link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="/static/css/login.css"> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row col-md-4 col-lg-offset-4 container"> <form method=post> {% csrf_token %} <h1 class="form-signin-heading col-lg-offset-4 text-primary"><b>請登陸:</b></h1> <hr> <div> <label for="username">用戶名:</label> <p class="username"><input id="username" class="form-control" placeholder="用戶名" type="text" name="username"></p> </div> <div> <label for="password">密碼:</label> <p class="password"><input id="password" class="form-control" placeholder="密碼" type="password" name="password"></p> </div> <div> <label for="auth_code">驗證碼:</label> <p class="auth_code"><input id="auth_code" class="form-control" placeholder="驗證碼" type="text" name="auth_code"></p> </div> <div> <img class="auth_code_img" src="/get_authCode_img/" style="width:200px;height:50px"> {# <a class="refresh">看不清</a>#} </div> <hr> <input type="button" value="登陸" class="btn btn-lg btn-primary pull-left" id="subBtn"><span class="error"></span> <a href="/register/"> <input type="button" value="註冊" class="btn btn-lg btn-primary pull-right" id=""></a> </form> </div> </div> <script> //登陸 $("#subBtn").click(function () { $.ajax({ url:"/login/", type:"POST", data:{ "username":$("#username").val(), "password":$("#password").val(), "auth_code":$("#auth_code").val(), "csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val() }, success:function (data) { console.log(data); var response=JSON.parse(data); if (response["is_login"]){ location.href="/index/" } else { $(".error").html(response["error_msg"]).css("color","red") } } }) }); // 驗證碼刷新 $(".auth_code_img").click(function () { $(this)[0].src+="?" }) </script> </body> </html>
後端代碼:
登陸 def login(request): if request.is_ajax(): login_response = {"is_login": False, "error_msg": None} # 定義一個字典 username = request.POST.get("username") # 取到用戶名 password = request.POST.get("password") # 取到密碼 auth_code = request.POST.get("auth_code") # 取到驗證碼 if auth_code.upper() == request.session.get("auth_code").upper(): # 從session中獲取驗證碼,判斷是否正確 # print(username, password, '==========') user = auth.authenticate(username=username, password=password) print(user) # 經過auth模塊獲取用戶名密碼 if user: # 正確,判斷用戶名和密碼是否正確 login_response["is_login"] = True auth.login(request, user) else: login_response["error_msg"] = "用戶名或密碼不正確" # 前端顯示用戶名或密碼錯誤 else: login_response["error_msg"] = '驗證碼不正確' # 前端顯示驗證碼錯誤 return HttpResponse(json.dumps(login_response)) # 返回 return render(request, "login.html") # 若不是Ajax訪問方式,返回登陸頁面從新登陸
驗證碼:
# 登陸 def login(request): if request.is_ajax(): login_response = {"is_login": False, "error_msg": None} # 定義一個字典 username = request.POST.get("username") # 取到用戶名 password = request.POST.get("password") # 取到密碼 auth_code = request.POST.get("auth_code") # 取到驗證碼 if auth_code.upper() == request.session.get("auth_code").upper(): # 從session中獲取驗證碼,判斷是否正確 # print(username, password, '==========') user = auth.authenticate(username=username, password=password) print(user) # 經過auth模塊獲取用戶名密碼 if user: # 正確,判斷用戶名和密碼是否正確 login_response["is_login"] = True auth.login(request, user) else: login_response["error_msg"] = "用戶名或密碼不正確" # 前端顯示用戶名或密碼錯誤 else: login_response["error_msg"] = '驗證碼不正確' # 前端顯示驗證碼錯誤 return HttpResponse(json.dumps(login_response)) # 返回 return render(request, "login.html") # 若不是Ajax訪問方式,返回登陸頁面從新登陸
驗證碼刷新:
// 驗證碼刷新 $(".auth_code_img").click(function () { $(this)[0].src+="?" })
註銷:
#註銷 def log_out(request): auth.logout(request) return redirect("/login/")
css代碼:
.container{ margin-top:20px; }
請求流程:
流程:
1:客戶端-----------發送(第一次get請求)-------------客戶端返回一個Html頁面(登陸頁面) 2:驗證碼-----------src(url再次請求服務端)----------服務端執行驗證碼函數,生成驗證碼保存在session中 3:用戶輸入內容----點擊提交發送ajax請求---(Post)----服務端從request中拿到ajax請求信息。 4:從session中取出取出驗證碼和--ajax中的信息進行匹配。 5:匹配成功---------進行下一步驗證,失敗返回錯誤信息,在Html頁面渲染。 6:經過auth模塊獲取用戶名密碼,判斷用戶名和密碼是否和數據庫中的相同。 7:若相同,寫入定義的字典中。 一「is_login」:true-----保存在session中,跳轉到首頁 8:若不相同,返回登陸頁面,渲染錯誤信息。
1,用ajax提交數據 $(".log_btn").click(function(){ $.ajax({ url:url路徑 type:訪問狀態 headers: {"X-CSRFToken":
$.cookie('csrftoken')},#跨站請求訪問 返回的數據 data:{ 字典名:$(".字段標識名").val() } 接收數據 sussecc:funsess(data){ 函數 } }) }
二、圖片刷新(寫在sussecc函數中) 原理:給圖片綁定一個點擊事件:每次給src+?就會再次發送一次get請求,就起到了刷星的做用 dom對象 $(".validCode_img")
.click(function () { $(this)[0].src+="?";
隨機驗證碼:
方式一:將圖片導入靜態文件,用文件句柄打開圖片返回給前端進行渲染
方式二:導入PIL模塊,利用Image生成一張圖片保存後,用文件舉兵打開,返回前端
方式三:導入PIL、IO模塊,仍是利用Image生成圖片,可是此次沒有將圖片保存到磁盤而是將圖片利用IO模塊中的BytesIO暫時的保存到內存中,用BytesIO句柄打開,返回到前端。
方式四:對方式三進行優化,加上了random模塊可讓圖片隨機生成,加上隨機的5個字符,基本的驗證碼就顯示出來了
由於隨機碼是用for循環生成的先將它放入一個列表中,人後將列表轉換 爲字符串,存入session中便於作對比,接收前端發過來的數據,包括用 戶名密碼以及驗證碼三條數據,先拿session中保存的驗證碼與前段發來 的驗證碼進行匹配驗證,若是匹配成功則進行用戶名密碼的匹配匹配成功 則登陸成功
def get_authCode_img(request): #方式一 # import os # path = os.path.join(settings.BASE_DIR, "static", "img", "a.jpg") # with open(path, "rb") as f: # data = f.read() # return HttpResponse(data) # 方式2: # from PIL import Image # img=Image.new(mode="RGB",size=(120,40),color="green") # f=open("validCode.png","wb") # img.save(f,"png") # with open("validCode.png","rb") as f: # data=f.read() # return HttpResponse(data) # 方式3: # from io import BytesIO # from PIL import Image # img = Image.new(mode="RGB", size=(120, 40), color="blue") # f=BytesIO() # img.save(f,"png") # data=f.getvalue() # return HttpResponse(data) # 方式4 : from io import BytesIO import random from PIL import Image,ImageDraw,ImageFont img = Image.new(mode="RGB", size=(120, 40), color=(random.randint(0,255),random.randint(0,255),random.randint(0,255))) draw=ImageDraw.Draw(img,"RGB") font=ImageFont.truetype("static/font/kumo.ttf",25) valid_list=[] for i in range(5): random_num=str(random.randint(0,9)) random_lower_zimu=chr(random.randint(65,90)) random_upper_zimu=chr(random.randint(97,122)) random_char=random.choice([random_num,random_lower_zimu,random_upper_zimu]) draw.text([5+i*24,10],random_char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font) valid_list.append(random_char) f=BytesIO() img.save(f,"png") data=f.getvalue() valid_str="".join(valid_list) print(valid_str) request.session["Keep_auth_code"]=valid_str #將驗證碼寫入session中 return HttpResponse(data)
三:註冊:
頁面
form組件:
#! usr/bin/env python # -*- coding: utf-8 -*- from django import forms from django.forms import fields from django.forms import widgets,ValidationError from app01 import models from django.core.validators import RegexValidator class RegisterForm(forms.Form): """註冊Form組件""" username = forms.CharField( required=True, min_length=3, max_length=8, error_messages={ 'required': '用戶不能爲空', 'min_length': '用戶長度不能小於3', 'max_length': '用戶長度不能大於8', },widget=widgets.TextInput(attrs={'placeholder': '用戶名:', 'class': 'form-control'})) password = fields.CharField( required=True, min_length=3, max_length=8, error_messages={ 'required': '密碼不能爲空', 'min_length': '密碼長度不能小於3', 'max_length': '密碼長度不能大於8', # 'invalid': '密碼格式錯誤', }, # validators=[RegexValidator('\d+', '只能是數字')], widget=widgets.PasswordInput(attrs={'placeholder': '密碼:', 'class': 'form-control'})) confirm_password = fields.CharField( required=True, min_length=3, max_length=8, error_messages={ 'required': '確認密碼不能爲空', 'min_length': '確認密碼長度不能小於3', 'max_length': '確認密碼長度不能大於8', }, widget=widgets.PasswordInput(attrs={'placeholder': '確認密碼:', 'class': 'form-control'})) email = fields.EmailField( required=True, error_messages={ 'required':'郵箱不能爲空', 'invalid':'郵箱格式錯誤'}, widget=widgets.EmailInput(attrs={'placeholder':'郵箱:','class':'form-control'})) def clean_username(self): """用戶名""" ret = models.UserInfo.objects.filter(username=self.cleaned_data.get("username")) if not ret: return self.cleaned_data.get("username") else: raise ValidationError("用戶名已註冊") def clean_password(self): """密碼""" data = self.cleaned_data.get("password") if not data.isdigit(): return self.cleaned_data.get("password") else: raise ValidationError("密碼不能全是數字") # def clean_auth_code(self): # if self.cleaned_data.get("auth_code")==self.request.session.get("auth_code"): # return self.cleaned_data.get("auth_code") # else: # raise ValidationError("驗證碼錯誤") def clean(self): if self.cleaned_data.get("password")==self.cleaned_data.get("confirm_password"): return self.cleaned_data else: raise ValidationError("兩次密碼不一致") def __init__(self,request,*args,**kwargs): super().__init__(*args,**kwargs) self.request=request
前端頁面顯示:
from django.shortcuts import render, HttpResponse, redirect from app01.forms import * from app01 import forms from app01 import models from django.db.models import Count import json from django.contrib import auth # 登陸 def login(request): if request.is_ajax(): login_response = {"is_login": False, "error_msg": None} # 定義一個字典 username = request.POST.get("username") # 取到用戶名 password = request.POST.get("password") # 取到密碼 auth_code = request.POST.get("auth_code") # 取到驗證碼 if auth_code.upper() == request.session.get("auth_code").upper(): # 從session中獲取驗證碼,判斷是否正確 # print(username, password, '==========') user = auth.authenticate(username=username, password=password) print(user) # 經過auth模塊獲取用戶名密碼 if user: # 正確,判斷用戶名和密碼是否正確 login_response["is_login"] = True auth.login(request, user) else: login_response["error_msg"] = "用戶名或密碼不正確" # 前端顯示用戶名或密碼錯誤 else: login_response["error_msg"] = '驗證碼不正確' # 前端顯示驗證碼錯誤 return HttpResponse(json.dumps(login_response)) # 返回 return render(request, "login.html") # 若不是Ajax訪問方式,返回登陸頁面從新登陸 # 驗證碼 def get_authCode_img(request): from io import BytesIO import random from PIL import Image, ImageDraw, ImageFont img = Image.new(mode="RGB", size=(120, 40), color=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))) draw = ImageDraw.Draw(img, "RGB") font = ImageFont.truetype("static/font/kumo.ttf", 25) valid_list = [] for i in range(5): random_num = str(random.randint(0, 9)) random_lower_zimu = chr(random.randint(65, 90)) random_upper_zimu = chr(random.randint(97, 122)) random_char = random.choice([random_num, random_lower_zimu, random_upper_zimu]) draw.text([5 + i * 24, 10], random_char, (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)), font=font) valid_list.append(random_char) f = BytesIO() img.save(f, "png") data = f.getvalue() valid_str = "".join(valid_list) print(valid_str) request.session["auth_code"] = valid_str # 將驗證碼寫入session中 return HttpResponse(data) #註銷 def log_out(request): auth.logout(request) return redirect("/login/") # 註冊 def register(request): if request.is_ajax(): form_obj = forms.RegisterForm(request,request.POST) print("---------") print(form_obj.is_valid()) regResponse = {"user": None, "errorsList": None} if form_obj.is_valid(): print("000000") username = form_obj.cleaned_data["username"] password = form_obj.cleaned_data["password"] # nickname = form_obj.cleaned_data["nickname"] # tel = form_obj.cleaned_data["tel"] email = form_obj.cleaned_data.get("email") avatar_img = request.FILES.get("avatar_img") user_obj = models.UserInfo.objects.create_user(username=username, password=password,email=email,avatar=avatar_img) regResponse["user"] = user_obj.username else: print("111") regResponse["errorsList"] = form_obj.errors print(regResponse) return HttpResponse(json.dumps(regResponse)) form_obj= forms.RegisterForm(request) return render(request, "register.html", {"form_obj": form_obj}) # 主頁 def index(request,*args,**kwargs): if kwargs: article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找點擊的類的文章 else: article_list = models.Article.objects.all() site_list = models.SiteCategory.objects.all() return render(request, "index.html",{"article_list":article_list,"site_list":site_list}) #我的主頁 def homeSite(request,username,**kwargs): # print(kwargs) # print(username) """點擊文章用戶名或,頭像跳轉的此頁""" current_user = models.UserInfo.objects.filter(username=username).first()#獲取當前用戶 # current_blog = current_user.blog#獲取當前博客 if not current_user: return render(request,"notFound.html") current_blog = current_user.blog # 獲取當前博客 #查詢當前文章 article_list=models.Article.objects.filter(user=current_user) #查詢 當前用戶的分類歸檔 classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c") #查詢當前用戶的標籤歸檔 tag_list=models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name","c") #查詢當前用戶的標籤歸檔 date_list = models.Article.objects.filter(user=current_user).extra( select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate(Count("id")) if kwargs: if kwargs.get("condition")=="classify": print(kwargs.get("condition")) article_list = models.Article.objects.filter(user=current_user,classify__title=kwargs.get("para")) # article_list = models.Article.objects.filter(user=current_user, category__title=kwargs.get("para")) elif kwargs.get("condition")=="tag": article_list = models.Article.objects.filter(user=current_user,tags__name=kwargs.get("para")) elif kwargs.get("condition")=="date": year,month=kwargs.get("para").aplit("/") article_list = models.Article.objects.filter(user=current_user,create_time__year=year,create_time__month=month) return render(request,"homeSite.html", locals()) #具體文章詳細 def contentsArticle(request,username,article_id): """點擊文章標題,跳轉到此頁""" current_user = models.UserInfo.objects.filter(username=username).first() # 獲取當前用戶 current_blog = current_user.blog#獲取當前博客 if not current_user: return render(request, "notFound.html") # 查詢當前文章 article_list = models.Article.objects.filter(user=current_user) # 查詢 當前用戶的分類歸檔 classfication_list = models.Classfication.objects.all().filter(blog=current_blog).annotate( c=Count("article__id")).values_list("title", "c") # 查詢當前用戶的標籤歸檔 tag_list = models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name", "c") # 查詢當前用戶的標籤歸檔 date_list = models.Article.objects.filter(user=current_user).extra( select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate( Count("id")) article_obj = models.Article.objects.filter(id=article_id).first() return render(request,"contents_article.html",loca
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>用戶註冊頁面</title> <link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <link href="/static/css/register.css" rel="stylesheet"> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/js/jquery.cookie.js"></script> </head> <body> <div class="container"> <div class="row col-md-4 col-lg-offset-4"> <form> {% csrf_token %} <h2 class="form-signin-heading col-lg-offset-3 text-info">請您註冊:</h2> <div class="form-group"> <label for="username">用戶名:</label> <p>{{ form_obj.username }} {{ form_obj.errors.username.0 }}</p> </div> <div class="form-group"> <label for="password">密碼:</label> <p>{{ form_obj.password }} {{ form_obj.errors.password.0 }}</p> </div> <div class="form-group"> <label for="confirm_password">確認密碼:</label> <p>{{ form_obj.confirm_password }} {{ form_obj.errors.confirm_password.0 }}</p> </div> {# <div class="form-group">#} {# <label for="nickname">暱稱:</label>#} {# <p>{{ form_obj.nickname }} {{ form_obj.errors.nickname.0 }}</p>#} {# </div>#} {# <div class="form-group">#} {# <label for="tel">電話:</label>#} {# <p>{{ form_obj.tel }} {{ form_obj.errors.tel.0 }}</p>#} {# </div>#} <div class="form-group"> <label for="email">郵箱:</label> <p>{{ form_obj.email }} {{ form_obj.errors.email.0 }}</p> </div> <div class="form-group avatar"> <label for="avatar">頭像</label> <img src="/static/img/default.png" alt="" id="avatar_img"> <input type="file" id="avatar_file"> </div > <div class="col-lg-offset-5"> <input type="button" value="提交" class="btn btn-primary" id="avatar_Btn"><span class="error"></span> </div> </form> </div> </div> <script> $("#avatar_file").change(function () { //頭像預覽 var ele_file = $(this)[0].files[0]; var reader = new FileReader(); reader.readAsDataURL(ele_file); reader.onload = function () { $("#avatar_img")[0].src = this.result } }); $("#avatar_Btn").click(function () { var formdata = new FormData(); formdata.append("username", $("#id_username").val()); formdata.append("password", $("#id_password").val()); formdata.append("confirm_password", $("#id_confirm_password").val()); {# formdata.append("nickname", $("#id_nickname").val());#} {# formdata.append("tel", $("#id_tel").val());#} formdata.append("email", $("#id_email").val()); formdata.append("avatar_img",$("#id_avatar_img").val()); $.ajax({ url: "/register/", type: "POST", data: formdata, contentType: false, processData: false, headers:{"X-CSRFToken":$.cookie('csrftoken')}, success: function (data) { console.log(data); var data = JSON.parse(data); if (data.user) { location.href = "/login/" } //全局鉤子的錯誤提示 else { console.log(data.errorsList); $(".pull-right").html("").parent().removeClass("has-error");//去除第一次錯誤信息 $.each(data.errorsList,function (i,j) { console.log(i,j); $span=$("<span>"); $span.addClass("pull-right").css("color","red");//給錯誤信息添加一個紅色 $span.html(j[0]); $("#id_"+i).after($span).parent().addClass("has-error");//找到當前錯誤的input框 if (i=="__all__"){ $("#id_confirm_password").after($span) } }) } } }) }) </script> </body> </html>
後端代碼:
def register(request): if request.is_ajax(): form_obj = forms.RegisterForm(request,request.POST) print("---------") print(form_obj.is_valid()) regResponse = {"user": None, "errorsList": None} if form_obj.is_valid(): print("000000") username = form_obj.cleaned_data["username"] password = form_obj.cleaned_data["password"] # nickname = form_obj.cleaned_data["nickname"] # tel = form_obj.cleaned_data["tel"] email = form_obj.cleaned_data.get("email") avatar_img = request.FILES.get("avatar_img") user_obj = models.UserInfo.objects.create_user(username=username, password=password,email=email,avatar=avatar_img) regResponse["user"] = user_obj.username else: print("111") regResponse["errorsList"] = form_obj.errors print(regResponse) return HttpResponse(json.dumps(regResponse)) form_obj= forms.RegisterForm(request) return render(request, "register.html", {"form_obj": form_obj})
css代碼:
.container{ margin-top:50px; } .avatar{ position: relative; width: 60px; height: 60px; } #avatar_img,#avatar_file{ position: absolute; top:0; left: 40px; width: 60px; height: 60px; } #avatar_file{ opacity: 0; }
頭像預覽JS:
/** * Created by pc on 2017-11-21. */ //頭像預覽 $("#avatar_file").change(function () { var ele_file = $(this)[0].files[0]; var reader = new FileReader(); reader.readAsDataURL(ele_file); reader.onload = function () { $("#avatar_img")[0].src = this.result } }); $("#avatar_Btn").click(function () { var formdata = new FormData(); formdata.append("username", $("#id_username")).val(); formdata.append("password", $("#id_password")).val(); formdata.append("confirm_password", $("#id_confirm_password")).val(); formdata.append("nickname", $("#id_nickname")).val(); formdata.append("tel", $("#id_tel")).val(); formdata.append("email", $("#id_email")).val(); formdata.append("avatar_img",$("#id_avatar_img")).val(); $.ajax({ url: "/register/", type: "POST", data: formdata, contentType: false, processData: false, header: {"X-CSRFToken": $.cookie('csrftoken')}, success: function (data) { console.log(data); var data = JSON.parse(data); if (data.user) { location.href = "/login/" } else { console.log(data.errorsList); $.each(data.errorsList, function (i, j) { console.log(i, j); $span = $("<span>"); $span.addClass("pull-right").css("color", "red"); $span.html(j[0]); $("#id_" + i).after($span).parent().addClass("has-error"); if (i=="__all__") { $("#id_repeat_pwd").after($span) } }) } } }) });
settings配置:
AUTH_USER_MODEL = "app01.UserInfo" STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,"static"), ] MEDIA_ROOT=os.path.join(BASE_DIR,"app01","media","uploads") MEDIA_URL="/media/"
流程:
註冊 1. form組件生成html標籤 在RegFrom類中繼承From這個類, 利用這個類的方法,生成input標籤,在這個類中可設置,標籤的屬性 - username - password - email 2. 利用後端傳來的form在前端生成html標籤 第一次get請求時後返回RegFrom類實例化的對象, 前端生成- username,- password,- emai,- avatar對應的四個標籤 顯示圖片: - 圖片和上傳文件摺疊 - 做用:上傳文件覆蓋圖片,透明度爲零 用戶點擊圖片其實點擊上傳文件 -把 - 把上傳文件和圖片的父親標籤設置爲相對路徑 設置長寬,本身 - 圖片預覽 - 用戶點擊上傳文件 上傳文件的標籤發生變化,會觸發change事件 - 取到用戶上傳的文件 var ele_file = this.files[0]; - 建立FileReader()對象4 - 把上傳文件的對象的路徑寫入FileReader()對象,結果爲FileReader().result - FileReader()加載onload事件,把FileReader().result結果寫入到img標籤 3. 用戶提交數據 用戶經過ajav提交數據: 若是要傳二進制的數據必需要用FormData打包 在傳二進制的時候必需要到的參數 -------contentType:false, ------processData:false, -----headers:{"X-CSRFToken":$.cookie('csrftoken')},防止跨站請求 --用FormData打包數據 var formdata=new FormData(); formdata.append("username",$("#id_username").val()); --經過data把數據傳到後臺函數 4.驗證數據 post請求走Regfrom函數 -有錯誤利用RegForm 的鉤子返回錯誤,----》 有錯誤將錯誤信息用鍵值對保存到errorst中 沒有錯誤將前端拿到的數據放入cleaned_data中 註冊函數中判斷form_obj.is_valid對象是否正確 ---正確則獲取數據寫入數據庫---返回一個狀態 regResponse["user"]=user_obj.username-----給前端 ---錯誤則獲取數據寫入數據庫---返回一個狀太regResponse["errorsList"]=form_obj.errors-----給前端 後臺函數利用form_obj.cleaned_data拿到數據 5、前端用ajax接收處理錯誤信息 $.each(data.errorsList,function (i,j) { {# controls.log(data.errorsList)#} {# console.log(i,j);#} // i j ------- username ["用戶名不能爲空"] ------- password ["密碼不能爲空"] ------- repeat_pwd ["驗證密碼不能爲空"] ------- email ["郵箱不能爲空"] $span=$("<span>"); $span.addClass("pull-right").css("color","red"); --------{# 添加一個span標籤#} $span.html(j[0]); --------{#把log的值j寫入span中#} $("#id_"+i).after($span).parent().addClass("has-error") -------#id_"+i找到當前的錯誤的input框 -------parent().addClass("has-error")給錯誤的input框加一個紅色的顏色 if (i=="__all__"){ $("#id_repeat_pwd").after($span) -------全局鉤子的錯誤信息 } })
四:博客主頁:
頁面:
前端代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale"> <title>{{username}}博客首頁</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> <link rel="stylesheet" href="/static/css/homeSite.css"> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> <div class="MenuBar"> <div class="heeder"> <div class="leftbutton"> <span class="abuttn">{{current_user.username}}</span> <a href="" class="abuttn">博客園</a> </div> <div class="key-search"> <form action="/" method="post"> <a href="#" class="i"> <span class="ico"></span> </a> </form> </div> <div class="rightbutton"> <a href="" class="abuttn">首頁</a> <a href="" class="abuttn">新隨筆</a> <a href="" class="abuttn">聯繫</a> <a href="" class="abuttn">訂閱</a> <a href="" class="abuttn">管理</a> </div> </div> </div> <div class="container homeSite"> <div class="row"> <div class="col-md-3 userinfo"> <div class="well well-lg "> <h4 class="col-lg-offset-3">我的信息</h4> <p>---------------------------------------------</p> <p><img src="{{current_user.avatar.url}}" alt="" width="100px" height="100px" class="img-circle"></p> <p>暱稱:    <span>{{current_user.username}}</span></p> <p>園齡:</p> <p>粉絲:</p> <p>關注:</p> <a href="">+關注</a> </div> <div class="panel panel-primary"> <div class="panel-heading"><b>分類歸檔</b></div> <div class="panel-body"> {% for classfication in classfication_list %} <p><a href="/app01/{{ current_user.username }}/classify/{{classfication.0}}">{{classfication.0}}({{classfication.1}})</a></p> {# <p>{{ classfication }}</p>#} {% endfor %} </div> <div class="panel-heading"><b>標籤歸檔</b></div> <div class="panel-body"> {% for tag in tag_list %} <p><a href="/app01/{{current_user.username}}/tag/{{tag.0}}">{{tag.0}}({{tag.1}})</a></p> {% endfor %} </div> <div class="panel-heading"><b>日期歸檔</b></div> <div class="panel-body"> {% for date in date_list %} <p><a href="/app01/{{current_user.username}}/date/{{date.0}}">{{date.0}}({{date.1}})</a></p> {% endfor %} </div> </div> </div> {# 文章#} <div class="col-md-9 articleinfo"> {% block content %} {% for article in article_list %} <div class="well well-lg "> <div class="col-lg-offset-9"> <h4>{{article.create_time|date:"Y年m月d日"}}</h4> </div> <p>---------------------------------------------------------------------------------------------------------------------------------------------------------------------------</p> <h3><a href="/app01/{{current_user.username}}/article/{{article.id}}"><b>{{article.title}}</b></a></h3> <hr> <div class="summary"> <p>{{article.summary}}<span><a href="">閱讀全文</a></span></p> </div> <hr> <div class="col-lg-offset-5 info"> 發表於:<span>{{article.create_time|date:"Y-m-d H:i"}}</span>   評論:<span>({{article.comment_count}})</span>   點贊:<span>({{article.poll_count}})</span>   閱讀:<span>({{article.read_count}})</span>     <span><a href="">編輯</a></span> </div> </div> {% endfor %} {% endblock %} </div> </div> </div> </body> </html>
後端代碼:
def index(request,*args,**kwargs): if kwargs: article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找點擊的類的文章 else: article_list = models.Article.objects.all() site_list = models.SiteCategory.objects.all() return render(request, "index.html",{"article_list":article_list,"site_list":site_list})
1:在url中寫主頁路由
url(r'^index', views.index)
url(r'^index', views.index),#主頁
2:建立視圖函數,從數據庫取出數據,返回到前端。
-------找到文章表,取出文章對象,返回。
-------找到網站分類表,取出分類對象,返回。
def index(request,*args,**kwargs): if kwargs: article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找點擊的類的文章 else: article_list = models.Article.objects.all() site_list = models.SiteCategory.objects.all() return render(request, "index.html",{"article_list":article_list,"site_list":site_list})
3:返回到主頁html進行渲染:
1:-----拿到文章對象用for標籤循環,{{.文章內容}}進行渲染。
<div class="col-md-6"> <div class=" article_list"> {% for article in article_list %} <div><a href="">{{article.title}}</a></div> <div class="row"> <div class="avatar col-md-2"> <a href="{% url 'aaa' article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a> </div> <div class="summary col-md-10" > <p>{{article.summary}}</p> </div> </div> <div class="article_info row">   <a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a>   發佈與:{{article.create_time|date:"Y-m-d H:i"}}   <a href=""><span class="glyphicon glyphicon-comment"></span>評論({{article.comment_count}})</a>   <a href=""><span class="glyphicon glyphicon-thumbs-up"></span>點贊({{article.poll_count}})</a>   <a href=""><span class="glyphicon glyphicon-share-alt"></span>閱讀({{article.read_count}})</a> </div> <hr> {% endfor %} </div>
2:-----拿到分類對象用for標籤循環,{{.網站分類,父}}進行渲染。
3:-----拿到網站分類對象,{{.(反向查詢,表名_set).網站分類,子}}進行渲染。
<div class="row col-md-3"> <div class="panel panel-primary"> <div class="panel-body"> 網站分類 </div> <div class="panel-footer"> {% for site in site_list %} <div class="panel panel-primary"> <div class="panel-heading cate_title">{{site.name}}</div> <div class="panel-body hides"> {% for sitearticlecategory in site.sitearticlecategory_set.all %} <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p> {% endfor %} </div> </div> {% endfor %} </div> </div> </div>
4:JQ作動態摺疊效果,鼠標懸浮展開,鼠標移開摺疊。
1:-----選擇器找到網站分類,給他綁定一個(懸浮)事件,當觸發這個事件(鼠標懸浮),執行function,$(this)找到選擇器對象,執行展開事件。
2:-----選擇器找到網站分類的父級,給他綁定一個(懸浮)執行function,$(this)找到選擇器對象,執行摺疊事件事件。
$(".cate_title").mouseover(function () { $(this).next().slideDown(300) }).parent().mouseleave(function () { $(this).children(".panel-footer").slideUp(300) });
5:點擊網站分類,子分類,查找到這個分類下的全部文章。
-------分類渲染在<a>標籤中,給他一個url,鼠標點擊,------走urls進行路由匹配--------找url的視圖函數--------進行查找
a標籤:---------/site/{{網站分類,name}}
url:------------以site開頭,有名分組(接收點擊的分類),按關鍵字傳參.*匹配全部,返回一個鍵值對,返回到視圖函數。
url(r'^site/(?P<site_article_category>.*)/$', views.index),
url(r'^site/(?P<site_article_category>.*)/$', views.index),
視圖函數--------**kwargs接收鍵值對,判斷kwargs,判斷正確,進行網站查詢,不然查詢全部文章。
查詢------------找到文章表,過濾(反向查詢按字段)出文章的網站分類,子分類 =kwargs傳過來的分類,返回到前端進行渲染。
article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))
def index(request,*args,**kwargs): if kwargs: article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找點擊的類的文
首頁:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale"> <title>博客系統首頁</title> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <style> .hides{ display: none; } </style> </head> <body> <nav class="navbar navbar-inverse primary"> <div class="container"> <a class="navbar-brand" href="#">博客園</a> <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse"> <ul class="nav navbar-nav navbar-right"> {# {% if request.user.is_authenticated %}#} <li><a href=""><span class="glyphicon glyphicon-user">{{request.user.uaername}}</span></a></li> <li><a href="/#/">註銷</a></li> <li><a href="/#/">修改密碼</a></li> {# {% else %}#} <li><a href="/#/">登陸</a></li> <li><a href="/#/">註冊</a></li> {# {% endif %}#} </ul> <form class="navbar-form navbar-right"> <input type="text" class="form-control" placeholder="搜索"> </form> </div> </div> </nav> <div class="container"> <div class="row col-md-3"> <div class="panel panel-primary"> <div class="panel-body"> 網站分類 </div> <div class="panel-footer"> {% for site in site_list %} <div class="panel panel-primary"> <div class="panel-heading cate_title">{{site.name}}</div> <div class="panel-body hides"> {% for sitearticlecategory in site.sitearticlecategory_set.all %} <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p> {% endfor %} </div> </div> {% endfor %} </div> </div> </div> <div class="col-md-6"> <div class=" article_list"> {% for article in article_list %} <div><a href="">{{article.title}}</a></div> <div class="row"> <div class="avatar col-md-2"> <a href="{% url 'aaa' article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a> </div> <div class="summary col-md-10" > <p>{{article.summary}}</p> </div> </div> <div class="article_info row">   <a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a>   發佈與:{{article.create_time|date:"Y-m-d H:i"}}   <a href=""><span class="glyphicon glyphicon-comment"></span>評論({{article.comment_count}})</a>   <a href=""><span class="glyphicon glyphicon-thumbs-up"></span>點贊({{article.poll_count}})</a>   <a href=""><span class="glyphicon glyphicon-share-alt"></span>閱讀({{article.read_count}})</a> </div> <hr> {% endfor %} </div> </div> <div class="col-md-3"> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> <div class="panel panel-default"> <div class="panel-body"> Panel content </div> <div class="panel-footer">Panel footer</div> </div> </div> </div> <script> $(".cate_title").mouseover(function () { $(this).next().slideDown(300) }).parent().mouseleave(function () { $(this).children(".panel-footer").slideUp(300) }); {# $(".cate_title").mouseenter(function () {#} {# $(this).next().slideDown(300)#} {# });#} {# $(".panel-footer").mouseleave(function () {#} {# $(this).next().slideUp(300)#} {# });#} </script> </body> </html>
四:我的博客主頁:
頁面:
前端代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale"> <title>{{username}}博客首頁</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> <link rel="stylesheet" href="/static/css/homeSite.css"> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> <div class="MenuBar"> <div class="heeder"> <div class="leftbutton"> <span class="abuttn">{{current_user.username}}</span> <a href="" class="abuttn">博客園</a> </div> <div class="key-search"> <form action="/" method="post"> <a href="#" class="i"> <span class="ico"></span> </a> </form> </div> <div class="rightbutton"> <a href="" class="abuttn">首頁</a> <a href="" class="abuttn">新隨筆</a> <a href="" class="abuttn">聯繫</a> <a href="" class="abuttn">訂閱</a> <a href="" class="abuttn">管理</a> </div> </div> </div> <div class="container homeSite"> <div class="row"> <div class="col-md-3 userinfo"> <div class="well well-lg "> <h4 class="col-lg-offset-3">我的信息</h4> <p>---------------------------------------------</p> <p><img src="{{current_user.avatar.url}}" alt="" width="100px" height="100px" class="img-circle"></p> <p>暱稱:    <span>{{current_user.username}}</span></p> <p>園齡:</p> <p>粉絲:</p> <p>關注:</p> <a href="">+關注</a> </div> <div class="panel panel-primary"> <div class="panel-heading"><b>分類歸檔</b></div> <div class="panel-body"> {% for classfication in classfication_list %} <p><a href="/app01/{{ current_user.username }}/classify/{{classfication.0}}">{{classfication.0}}({{classfication.1}})</a></p> {# <p>{{ classfication }}</p>#} {% endfor %} </div> <div class="panel-heading"><b>標籤歸檔</b></div> <div class="panel-body"> {% for tag in tag_list %} <p><a href="/app01/{{current_user.username}}/tag/{{tag.0}}">{{tag.0}}({{tag.1}})</a></p> {% endfor %} </div> <div class="panel-heading"><b>日期歸檔</b></div> <div class="panel-body"> {% for date in date_list %} <p><a href="/app01/{{current_user.username}}/date/{{date.0}}">{{date.0}}({{date.1}})</a></p> {% endfor %} </div> </div> </div> {# 文章#} <div class="col-md-9 articleinfo"> {% block content %} {% for article in article_list %} <div class="well well-lg "> <div class="col-lg-offset-9"> <h4>{{article.create_time|date:"Y年m月d日"}}</h4> </div> <p>---------------------------------------------------------------------------------------------------------------------------------------------------------------------------</p> <h3><a href="/app01/{{current_user.username}}/article/{{article.id}}"><b>{{article.title}}</b></a></h3> <hr> <div class="summary"> <p>{{article.summary}}<span><a href="">閱讀全文</a></span></p> </div> <hr> <div class="col-lg-offset-5 info"> 發表於:<span>{{article.create_time|date:"Y-m-d H:i"}}</span>   評論:<span>({{article.comment_count}})</span>   點贊:<span>({{article.poll_count}})</span>   閱讀:<span>({{article.read_count}})</span>     <span><a href="">編輯</a></span> </div> </div> {% endfor %} {% endblock %} </div> </div> </div> </body> </html>
後端代碼:
#我的主頁 def homeSite(request,username,**kwargs): # print(kwargs) # print(username) """點擊文章用戶名或,頭像跳轉的此頁""" current_user = models.UserInfo.objects.filter(username=username).first()#獲取當前用戶 # current_blog = current_user.blog#獲取當前博客 if not current_user: return render(request,"notFound.html") current_blog = current_user.blog # 獲取當前博客 #查詢當前文章 article_list=models.Article.objects.filter(user=current_user) #查詢 當前用戶的分類歸檔 classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c") #查詢當前用戶的標籤歸檔 tag_list=models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name","c") #查詢當前用戶的標籤歸檔 date_list = models.Article.objects.filter(user=current_user).extra( select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate(Count("id")) if kwargs: if kwargs.get("condition")=="classify": print(kwargs.get("condition")) article_list = models.Article.objects.filter(user=current_user,classify__title=kwargs.get("para")) # article_list = models.Article.objects.filter(user=current_user, category__title=kwargs.get("para")) elif kwargs.get("condition")=="tag": article_list = models.Article.objects.filter(user=current_user,tags__name=kwargs.get("para")) elif kwargs.get("condition")=="date": year,month=kwargs.get("para").aplit("/") article_list = models.Article.objects.filter(user=current_user,create_time__year=year,create_time__month=month) return render(request,"homeSite.html", locals())
url路由:
from django.conf.urls import include, url from django.contrib import admin from django.views.static import serve from Blog_long import settings from app01 import views urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^login', views.login), #登陸 url(r'^get_authCode_img/', views.get_authCode_img), #驗證碼 url(r'^log_out',views.log_out), #註銷 url(r'^register', views.register), # 註冊 url(r'^index', views.index),#主頁 # media 配置 url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}), #首頁點擊分類查詢到屬於這個類的文章 url(r'^site/(?P<site_article_category>.*)/$', views.index), #我的站點首頁,路由分發 url(r'^app01/', include('app01.urls')), ]
分發路由:
from django.conf.urls import include, url from app01 import views urlpatterns = [ url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite), url(r'^(?P<username>.*)/article/(?P<article_id>\d+)', views.contentsArticle), url(r'^(?P<username>.*)',views.homeSite,name="aaa"), ]
1:點擊首頁中的--頭像--和--發佈人--,跳轉到所對應的我的我的博客首頁中。
--頭像,發佈人都渲染在<a>標籤中。
--路由分發:以...開頭,就映入到某個應用下的urls中進行匹配。
url(r'^app01/', include('app01.urls')),
url(r'^app01/', include('app01.urls')),
--給a標籤一個url,點擊走----url進行路由匹配,匹配成功走----所對應的視圖函數。
url(r'^(?P<username>.*)', views.homeSite,name="aaa"),
<a>標籤:----------點擊發布人-----發送一個url:以app01/開頭,引入到app01下的urls中,當前點擊的用戶名。進行路由匹配。
"/app01/{{ article.user.username }}"
0
------點擊頭像-------經過別名,反向解析------找到別名是...的url,替換
------視圖函數中也能夠用反向解析,原理相同,導入removes,傳參數要用args。
{% url 'aaa' article.user.username %}
urls:-------------有名分組,按關鍵字傳參,接收當前點擊的用戶名,返回到所對應的視圖函數中,加別名,用於反向解析。
url(r'^(?P<username>.*)', views.homeSite,name="aaa"),
視圖函數:--------接收kwargs鍵值對,和當前用戶名-----查詢當前用戶名是點擊的用戶名,的用戶信息對象,判斷用戶信息,若是不是返回錯誤信息。
--返回我的博客頁面,返回用戶信息。
查詢:------------經過我的用戶信息查詢到我的我的站點(我的博客)
def homeSite(request,username,**kwargs): current_user = models.UserInfo.objects.filter(username=username).first()#獲取當前用戶 current_blog = current_user.blog print(current_blog)#獲取當前博客 if not current_user: return render(request,"notFound.html") #查詢當前文章 article_list=models.Article.objects.filter(user=current_user) #查詢 當前用戶的分類歸檔 classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c") #查詢當前用戶的標籤歸檔 tag_list=models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name","c") #查詢當前用戶的標籤歸檔 date_list = models.Article.objects.filter(user=current_user).extra( select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate( Count("id")) if kwargs: if kwargs.get("condition")=="classify": article_list = models.Article.objects.filter(user=username,classify__title=kwargs.get("para")) elif kwargs.get("condition")=="tag": article_list = models.Article.objects.filter(user=username,tags__name=kwargs.get("para")) elif kwargs.get("condition")=="date": year,month=kwargs.get("para").aplit("/") article_list = models.Article.objects.filter(user=username,create_time__year=year,create_time__month=month) return render(request,"homeSite.html", locals())
2:查詢當前用戶的文章對象-----找到文章表,過濾出user=當前用戶的文章,返回到頁面進行渲染。
3:拿到用戶信息,---------返回到頁面渲染我的信息。
4:分類歸檔
1:-----查詢當前用戶,我的站點的分類對象-----分組查詢到(查詢當前用戶,我的站點的分類對象)的數目
classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c")
2:-----返回到頁面進行渲染。
----for循環分類對象,是一個元組,.0拿到分類,.1拿到分類數量。進行渲染。
3:-----點擊當前分類------查詢到當前分類的文章進行渲染。
----<a>標籤-------當前分類渲染在a標籤中,點擊,發送一個url-----/app01/{{ current_user.username }}/classify/{{classfication.0}}----走urls。
----urls:---------以app01開頭,有名分組(當前用戶),有名分組(歸檔方式),有名分組(具體分類)-----返回當前用戶名,鍵值對到---視圖函數----走視圖函數。
url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
----視圖函數------拿到當前用戶名,鍵值對。
----判斷kwargs中有名分組(分類)等不等於歸檔分類 ----if kwargs.get("condition")=="classify":----判斷正確進行查詢
----查詢,-------查詢當前用戶我的站點所點擊分類的文章。-----返回到頁面進行渲染。
----article_list = models.Article.objects.filter(user=username,classify__title=kwargs.get("para"))
5:標籤歸檔-----點擊當前標籤------查詢到當前標籤的文章進行渲染。
----<a>標籤-------當前分類渲染在a標籤中,點擊,發送一個url-----/app01/{{ current_user.username }}/tag/{{classfication.0}}----走urls。
----urls:---------以app01開頭,有名分組(當前用戶),有名分組(歸檔方式),有名分組(具體標籤)-----返回當前用戶名,鍵值對到---視圖函數----走視圖函數。
url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
----視圖函數------拿到當前用戶名,鍵值對。
----判斷kwargs中有名分組(分類)等不等於歸檔標籤 ----if kwargs.get("condition")=="tag":----判斷正確進行查詢
----查詢,-------查詢當前用戶我的站點所點擊標籤的文章。-----返回到頁面進行渲染。
----article_list = models.Article.objects.filter(user=username,tags__name=kwargs.get("para"))
6:日期歸檔-----點擊當前日期------查詢到當前日期的文章進行渲染。
----<a>標籤-------當前分類渲染在a標籤中,點擊,發送一個url-----/app01/{{ current_user.username }}/data/{{classfication.0}}----走urls。
----urls:---------以app01開頭,有名分組(當前用戶),有名分組(歸檔方式),有名分組(具體日期)-----返回當前用戶名,鍵值對到---視圖函數----走視圖函數。
url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
----視圖函數------拿到當前用戶名,鍵值對。
----判斷kwargs中有名分組(日期)等不等於歸檔分類 ----if kwargs.get("condition")=="data":----判斷正確進行查詢
----查詢,-------查詢當前用戶我的站點所點擊標籤的文章。-----返回到頁面進行渲染。
----獲取時間----year,month=kwargs.get("para").aplit("/")
----article_list = models.Article.objects.filter(user=username,create_time__year=year,create_time__month=month)
我的博客首頁:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale"> <title>{{username}}博客首頁</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> <link rel="stylesheet" href="/static/css/homeSite.css"> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> <div class="MenuBar"> <div class="heeder"> <div class="leftbutton"> <span class="abuttn">{{current_user.username}}</span> <a href="" class="abuttn">博客園</a> </div> <div class="key-search"> <form action="/" method="post"> <a href="#" class="i"> <span class="ico"></span> </a> </form> </div> <div class="rightbutton"> <a href="" class="abuttn">首頁</a> <a href="" class="abuttn">新隨筆</a> <a href="" class="abuttn">聯繫</a> <a href="" class="abuttn">訂閱</a> <a href="" class="abuttn">管理</a> </div> </div> </div> <div class="container homeSite"> <div class="row"> <div class="col-md-3 userinfo"> <div class="well well-lg "> <h4 class="col-lg-offset-3">我的信息</h4> <p>---------------------------------------------</p> <p><img src="{{current_user.avatar.url}}" alt="" width="100px" height="100px" class="img-circle"></p> <p>暱稱:    <span>{{current_user.nickname}}</span></p> <p>園齡:</p> <p>粉絲:</p> <p>關注:</p> <a href="">+關注</a> </div> <div class="panel panel-primary"> <div class="panel-heading"><b>分類歸檔</b></div> <div class="panel-body"> {% for classfication in classfication_list %} <p><a href="/app01/{{ current_user.username }}/classify/{{classfication.0}}">{{classfication.0}}({{classfication.1}})</a></p> {# <p>{{ classfication }}</p>#} {% endfor %} </div> <div class="panel-heading"><b>標籤歸檔</b></div> <div class="panel-body"> {% for tag in tag_list %} <p><a href="/app01/{{current_user.username}}/tag/{{tag.0}}">{{tag.0}}({{tag.1}})</a></p> {% endfor %} </div> <div class="panel-heading"><b>日期歸檔</b></div> <div class="panel-body"> {% for date in date_list %} <p><a href="/app01/{{current_user.username}}/date/{{date.0}}">{{date.0}}({{date.1}})</a></p> {% endfor %} </div> </div> </div> {# 文章#} <div class="col-md-9 articleinfo"> {% for article in article_list %} <div class="well well-lg "> <div class="col-lg-offset-9"> <h4>{{article.create_time|date:"Y年m月d日"}}</h4> </div> <p>---------------------------------------------------------------------------------------------------------------------------------------------------------------------------</p> <h3><a href=""><b>{{article.title}}</b></a></h3> <hr> <div class="summary"> <p>{{article.summary}}<span><a href="">閱讀全文</a></span></p> </div> <hr> <div class="col-lg-offset-5 info"> 發表於:<span>{{article.create_time|date:"Y-m-d H:i"}}</span>   評論:<span>({{article.comment_count}})</span>   點贊:<span>({{article.poll_count}})</span>   閱讀:<span>({{article.read_count}})</span>     <span><a href="">編輯</a></span> </div> </div> {% endfor %} </div> </div> </div> </body> </html>
博客首頁-----和-----我的博客首頁--流程:
1:在url中寫主頁路由 url(r'^index', views.index) 2:建立視圖函數,從數據庫取出數據,返回到前端。 -------找到文章表,取出文章對象,返回。 -------找到網站分類表,取出分類對象,返回。 3:返回到主頁html進行渲染: 1:-----拿到文章對象用for標籤循環,{{.文章內容}}進行渲染。 2:-----拿到分類對象用for標籤循環,{{.網站分類,父}}進行渲染。 3:-----拿到網站分類對象,{{.(反向查詢,表名_set).網站分類,子}}進行渲染。 4:JQ作動態摺疊效果,鼠標懸浮展開,鼠標移開摺疊。 1:-----選擇器找到網站分類,給他綁定一個(懸浮)事件,當觸發這個事件(鼠標懸浮),執行function,$(this)找到選擇器對象,執行展開事件。 2:-----選擇器找到網站分類的父級,給他綁定一個(懸浮)執行function,$(this)找到選擇器對象,執行摺疊事件事件。 $(".cate_title").mouseover(function () { $(this).next().slideDown(300) }).parent().mouseleave(function () { $(this).children(".panel-footer").slideUp(300) }); 5:點擊網站分類,子分類,查找到這個分類下的全部文章。 -------分類渲染在<a>標籤中,給他一個url,鼠標點擊,------走urls進行路由匹配--------找url的視圖函數--------進行查找 a標籤:---------/site/{{網站分類,name}} url:------------以site開頭,有名分組(接收點擊的分類),按關鍵字傳參.*匹配全部,返回一個鍵值對,返回到視圖函數。 url(r'^site/(?P<site_article_category>.*)/$', views.index), 視圖函數--------**kwargs接收鍵值對,判斷kwargs,判斷正確,進行網站查詢,不然查詢全部文章。 查詢------------找到文章表,過濾(反向查詢按字段)出文章的網站分類,子分類 =kwargs傳過來的分類,返回到前端進行渲染。 article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category")) 四:我的博客主頁: 1:點擊首頁中的--頭像--和--發佈人--,跳轉到所對應的我的我的博客首頁中。 --頭像,發佈人都渲染在<a>標籤中。 --路由分發:以...開頭,就映入到某個應用下的urls中進行匹配。 url(r'^app01/', include('app01.urls')), --給a標籤一個url,點擊走----url進行路由匹配,匹配成功走----所對應的視圖函數。 <a>標籤:----------點擊發布人-----發送一個url:以app01/開頭,引入到app01下的urls中,當前點擊的用戶名。進行路由匹配。 "/app01/{{ article.user.username }}" 0 ------點擊頭像-------經過別名,反向解析------找到別名是...的url,替換 ------視圖函數中也能夠用反向解析,原理相同,導入removes,傳參數要用args。 {% url 'aaa' article.user.username %} urls:-------------有名分組,按關鍵字傳參,接收當前點擊的用戶名,返回到所對應的視圖函數中,加別名,用於反向解析。 url(r'^(?P<username>.*)', views.homeSite,name="aaa"), 視圖函數:--------接收kwargs鍵值對,和當前用戶名-----查詢當前用戶名是點擊的用戶名,的用戶信息對象,判斷用戶信息,若是不是返回錯誤信息。 --返回我的博客頁面,返回用戶信息。 查詢:------------經過我的用戶信息查詢到我的我的站點(我的博客) 2:查詢當前用戶的文章對象-----找到文章表,過濾出user=當前用戶的文章,返回到頁面進行渲染。 3:拿到用戶信息,---------返回到頁面渲染我的信息。 4:分類歸檔 1:-----查詢當前用戶,我的站點的分類對象-----分組查詢到(查詢當前用戶,我的站點的分類對象)的數目 classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c") 2:-----返回到頁面進行渲染。 ----for循環分類對象,是一個元組,.0拿到分類,.1拿到分類數量。進行渲染。 3:-----點擊當前分類------查詢到當前分類的文章進行渲染。 ----<a>標籤-------當前分類渲染在a標籤中,點擊,發送一個url-----/app01/{{ current_user.username }}/classify/{{classfication.0}}----走urls。 ----urls:---------以app01開頭,有名分組(當前用戶),有名分組(歸檔方式),有名分組(具體分類)-----返回當前用戶名,鍵值對到---視圖函數----走視圖函數。 url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite), ----視圖函數------拿到當前用戶名,鍵值對。 ----判斷kwargs中有名分組(分類)等不等於歸檔分類 ----if kwargs.get("condition")=="classify":----判斷正確進行查詢 ----查詢,-------查詢當前用戶我的站點所點擊分類的文章。-----返回到頁面進行渲染。 ----article_list = models.Article.objects.filter(user=username,classify__title=kwargs.get("para")) 5:標籤歸檔-----點擊當前標籤------查詢到當前標籤的文章進行渲染。 ----<a>標籤-------當前分類渲染在a標籤中,點擊,發送一個url-----/app01/{{ current_user.username }}/tag/{{classfication.0}}----走urls。 ----urls:---------以app01開頭,有名分組(當前用戶),有名分組(歸檔方式),有名分組(具體標籤)-----返回當前用戶名,鍵值對到---視圖函數----走視圖函數。 url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite), ----視圖函數------拿到當前用戶名,鍵值對。 ----判斷kwargs中有名分組(分類)等不等於歸檔標籤 ----if kwargs.get("condition")=="tag":----判斷正確進行查詢 ----查詢,-------查詢當前用戶我的站點所點擊標籤的文章。-----返回到頁面進行渲染。 ----article_list = models.Article.objects.filter(user=username,tags__name=kwargs.get("para")) 6:日期歸檔-----點擊當前日期------查詢到當前日期的文章進行渲染。 ----<a>標籤-------當前分類渲染在a標籤中,點擊,發送一個url-----/app01/{{ current_user.username }}/data/{{classfication.0}}----走urls。 ----urls:---------以app01開頭,有名分組(當前用戶),有名分組(歸檔方式),有名分組(具體日期)-----返回當前用戶名,鍵值對到---視圖函數----走視圖函數。 url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite), ----視圖函數------拿到當前用戶名,鍵值對。 ----判斷kwargs中有名分組(日期)等不等於歸檔分類 ----if kwargs.get("condition")=="data":----判斷正確進行查詢 ----查詢,-------查詢當前用戶我的站點所點擊標籤的文章。-----返回到頁面進行渲染。 ----獲取時間----year,month=kwargs.get("para").aplit("/") ----article_list = models.Article.objects.filter(user=username,create_time__year=year,create_time__month=month)
五:文章詳細(重點:點贊,評論)
解決bug:登陸點贊,不登陸返回登陸頁面。
六:後臺管理
1:後臺頁面設計:-----------------給(管理)a標籤一個路由:/app01/manage/
url:
url(r'^manage/$',views.manage),
前端代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale"> <title>後臺管理</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <script src="/static/kindeditor/kindeditor-all-min.js"></script> </head> <body> <div class="" style="background-color: #2459a2;height: 50px;width: 100%"> <div class="container"> <a class="navbar-brand" href="#"><b>{{ user.username }}博客園後臺管理</b></a> <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse"> <ul class="nav navbar-nav navbar-right"> <li><a href="/logout/">註銷</a></li> <li><a href="/setpassword/">修改密碼</a></li> </ul> </div> </div> </div> <p></p> <div class="row col-md-2"> <div class="panel panel-primary "> <div class="panel-heading"><b>操做</b></div> <div class="panel-body"> <div class="panel-footer"><a href="/app01/manage/"><< 文章管理 >></a></div> <div class="panel-footer"><a href=""><< 分類管理 >></a></div> <div class="panel-footer"><a href=""><< 標籤管理 >></a></div> <div class="panel-footer"><h2>{{ user }}!</h2></div> </div> </div> </div> <div class="col-md-9 sidebar alert-warning col-lg-offset-1"> {% block manage %} <div class="bs-example" data-example-id="contextual-table"> <table class="table"> <thead> <tr> <th>標題</th> <th>評論數</th> <th>點贊數</th> <th>操做</th> <th>操做</th> <th><a href="/app01/manage/add_article/"> <button class="btn btn-primary">添加</button> </a></th> </tr> </thead> <tbody> {% for article in article_list %} <tr> <td>{{ article.title }}</td> <td>{{ article.comment_count }}</td> <td>{{ article.poll_count }}</td> <td><a href=""> <button class="btn btn-primary">編輯</button> </a></td> <td><a href=""> <button class="btn btn-danger">刪除</button> </a></td> </tr> {% endfor %} </tbody> </table> </div> {% endblock %} </div> </body> </html>
後端代碼:
def manage(request): if not request.user.is_authenticated(): return redirect("/login/") article_list = models.Article.objects.filter(user=request.user).all() print(article_list) return render(request,"manage.html",{"article_list":article_list})
2:文章管理:
----添加文章:
url:
url(r'^manage/add_article/$',views.add_article),
前端代碼:
{% extends "manage.html"%} {% block manage %} {% csrf_token %} <h4>添加文章:</h4> <form action="/app01/manage/add_article/" method="post" novalidate> {% csrf_token %} <div> <label for="title">標題:</label> <p>{{ article_form.title }} {{ article_form.errors.title.0 }}</p> </div> <div> <label for="content">內容:</label> <p>{{ article_form.content }} {{ article_form.errors.content.0 }}</p> </div> <p><button class="btn-sm btn-primary">提交</button></p> </form> <script> KindEditor.ready(function (K) { window.editor = K.create('#id_content', { {# 寬#} width: "1100px", {# 高#} height: "450px", {# 是否能夠拖動#} resizeType: 0, {# 指定上傳文件的終端,對應在url,視圖函數#} uploadJson: "/uploadFile/", extraFileUploadParams: { csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val() } }); }) </script> {% endblock %}
添加文章Form組件:
#文章From組件 class ArticleFrom(forms.Form): title = forms.CharField( required=True, max_length=20, error_messages={ "required":"不能爲空", },widget=widgets.TextInput(attrs={ 'class': 'form-control'})) content = forms.CharField( required=True, error_messages={ "required": "不能爲空", },widget=widgets.Textarea(attrs={ 'class': 'form-control'})) def clean_content(self): # 拿到文章內容 html_str=self.cleaned_data.get("content") #調用函數 clean_content=xss_plugin.filter_xss(html_str) self.cleaned_data["content"]=clean_content return self.cleaned_data.get("content")
後端代碼:
def add_article(request): if request.method=="POST": article_form = ArticleFrom(request.POST) if article_form.is_valid(): title = article_form.cleaned_data.get("title") content = article_form.cleaned_data.get("content") article_obj = models.Article.objects.create(title=title,summary=content[0:30],create_time=datetime.datetime.now(),user=request.user) models.Article_detail.objects.create(content=content,article=article_obj) return HttpResponse("添加成功") else: pass article_form=ArticleFrom return render(request,"add_article.html",{"article_form":article_form})
3:添加kindeditor編輯器
下載:http://kindeditor.net/docs/option.html
編輯器(kindeditor)--------------------------------------http://kindeditor.net/docs/option.html
導入:
引用:
綁定編輯器:
代碼:
url:
#編輯器上傳文件 url(r'^uploadFile/$', views.uploadFile),
視圖函數:-----------------文件預覽
4:XSS攻擊----用(beautifulsoup4模塊實現)
(beautifulsoup4)----------------------------------------http://www.cnblogs.com/yuanchenqi/articles/7617280.html
----下載:
----xss組件:
代碼:
from bs4 import BeautifulSoup def filter_xss(html_str): valid_tag_list = ["p", "div", "a", "img", "html", "body", "br", "strong", "b"] valid_dict = {"p": ["id", "class"], "div": ["id", "class"]} soup = BeautifulSoup(html_str, "html.parser") # soup -----> document ######### 改爲dict for ele in soup.find_all(): # 過濾非法標籤 if ele.name not in valid_dict: ele.decompose() # 過濾非法屬性 else: attrs = ele.attrs # p {"id":12,"class":"d1","egon":"dog"} l = [] for k in attrs: if k not in valid_dict[ele.name]: l.append(k) for i in l: del attrs[i] print(soup) return soup.decode()
-----from組件 過濾,鉤子
代碼:
from django import forms from django.forms import fields from django.forms import widgets,ValidationError from app01 import models from app01.plugins import xss_plugin from django.core.validators import RegexValidator #註冊Form組件 class RegisterForm(forms.Form): """註冊Form組件""" username = forms.CharField( required=True, min_length=3, max_length=8, error_messages={ 'required': '用戶不能爲空', 'min_length': '用戶長度不能小於3', 'max_length': '用戶長度不能大於8', },widget=widgets.TextInput(attrs={'placeholder': '用戶名:', 'class': 'form-control'})) password = fields.CharField( required=True, min_length=3, max_length=8, error_messages={ 'required': '密碼不能爲空', 'min_length': '密碼長度不能小於3', 'max_length': '密碼長度不能大於8', # 'invalid': '密碼格式錯誤', }, # validators=[RegexValidator('\d+', '只能是數字')], widget=widgets.PasswordInput(attrs={'placeholder': '密碼:', 'class': 'form-control'})) confirm_password = fields.CharField( required=True, min_length=3, max_length=8, error_messages={ 'required': '確認密碼不能爲空', 'min_length': '確認密碼長度不能小於3', 'max_length': '確認密碼長度不能大於8', }, widget=widgets.PasswordInput(attrs={'placeholder': '確認密碼:', 'class': 'form-control'})) email = fields.EmailField( required=True, error_messages={ 'required':'郵箱不能爲空', 'invalid':'郵箱格式錯誤'}, widget=widgets.EmailInput(attrs={'placeholder':'郵箱:','class':'form-control'})) def clean_username(self): """用戶名""" ret = models.UserInfo.objects.filter(username=self.cleaned_data.get("username")) if not ret: return self.cleaned_data.get("username") else: raise ValidationError("用戶名已註冊") def clean_password(self): """密碼""" data = self.cleaned_data.get("password") if not data.isdigit(): return self.cleaned_data.get("password") else: raise ValidationError("密碼不能全是數字") # def clean_auth_code(self): # if self.cleaned_data.get("auth_code")==self.request.session.get("auth_code"): # return self.cleaned_data.get("auth_code") # else: # raise ValidationError("驗證碼錯誤") def clean(self): if self.cleaned_data.get("password")==self.cleaned_data.get("confirm_password"): return self.cleaned_data else: raise ValidationError("兩次密碼不一致") def __init__(self,request,*args,**kwargs): super().__init__(*args,**kwargs) self.request=request #文章From組件 class ArticleFrom(forms.Form): title = forms.CharField( required=True, max_length=20, error_messages={ "required":"不能爲空", },widget=widgets.TextInput(attrs={ 'class': 'form-control'})) content = forms.CharField( required=True, error_messages={ "required": "不能爲空", },widget=widgets.Textarea(attrs={ 'class': 'form-control'})) def clean_content(self): # 拿到文章內容 html_str=self.cleaned_data.get("content") #調用函數 clean_content=xss_plugin.filter_xss(html_str) self.cleaned_data["content"]=clean_content return self.cleaned_data.get("content")