Moni,我是Charlie!
在Day27当中我们完成了recaptcha验证,而今天我们将实作按赞收藏的部分。
================================◉‿◉=================================
首先是後端的部分,按赞收藏需要另外一个资料表,这个资料表会包含以下栏位:
所以我们先新建一个app叫做favorite:
*$ python manage.py startapp favorite
接着在settings.py当中新增INSTALLED_APPS:
INSTALLED_APPS = [
….
'users',
'login',
'resetPWD',
'favorite'...
]
并在favorite APP当中建立models:
from django.db import models
from users.models import User
from product.models import Product
# Create your models here.
class Favorite(models.Model):
id = models.AutoField(primary_key = True)
user = models.ForeignKey(User,on_delete = models.CASCADE,verbose_name = "用户")
product = models.ForeignKey(Product,on_delete = models.CASCADE,verbose_name = "商品")
created_time = models.DateTimeField(auto_now = True,verbose_name = "创建时间")
modified_time = models.DateTimeField(auto_now = True,verbose_name = "修改时间")
status = models.IntegerField(verbose_name = "状态")
class Meta:
db_table = "favorite"
并使用指令迁移:
$ python manage.py makemigrations favorite
$ python manage.py migrate favorite
接着建立urls.py,并且修改keyboardmarket\urls.py,新增favorite app url:
keyboardmarket\urls.py
urlpatterns = [
path('admin/', admin.site.urls),
url('favorite',include('favorite.urls')),
url('reset',include('resetPWD.urls')),
url('usercart',include('usercart.urls')),
url('userorder',include('userorder.urls')),
url('user',include('users.urls')),
url('login',include('login.urls')),
url('product',include('product.urls')),
]
favorite\urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$',views.favorite)
]
favorite APP会处理三种请求:
所以在views.py当中建立基本程序码:
from tools.login_check import logincheck
from tools.R import R
from favorite.models import Favorite
from users.models import User
from product.models import Product
from tools.db import FavoriteStatus
import json
# Create your views here.
@logincheck("GET","POST")
def favorite(request,productID = None):
if request.method == "GET" and productID:
pass
if request.method == "GET":
pass
if request.method == "POST":
pass
return R.methodNotAllowed("method not allowed")
接着在tools\db.py当中建立FavoriteStatus:
class FavoriteStatus(Enum):
deactivate = 0
activate = 1
然後在Favorite model建立toJson方法:
def toJson(self):
data = {}
data["id"] = self.id
data["username"] = self.user.name
data["product"] = self.product.toJson()
data["created_time"] = self.created_time
data["modified_time"] = self.modified_time
data["status"] = self.status
return data
先修改GET的部分,GET会读到username的参数,如果有读到的话就会查询按赞纪录,并返回资料:
if request.method == "GET":
req = request.GET
if "username" not in req:
return R.badRequest("username does not exist")
username = req["username"]
user = User.objects.filter(name = username)
if not user:
return R.badRequest("User not found")
user = user[0]
favorites = Favorite.objects.filter(user = user).filter(status = FavoriteStatus.activate.value)
favorites = [i.toJson() for i in favorites]
return R.ok(favorites)
再来是POST的部分,这部分需要判断的比较多,如果没有此笔资料的话要新增按赞资料,如果有此笔资料的话如果状态为1就更改为状态为0,如果状态为0则更改状态为1:
if request.method == "POST":
req = request.body
data = json.loads(req)
if "username" not in data or "pid" not in data:
return R.badRequest("not enough parameters!")
username = data["username"]
user = User.objects.filter(name = username)
if not user:
return R.badRequest("User not found")
user = user[0]
pid = data["pid"]
product = Product.objects.filter(id = pid)
if not product:
return R.badRequest("product does not exist!")
product = product[0]
favorite = Favorite.objects.filter(user = user).filter(product = product)
if not favorite:
favorite = Favorite.objects.create(
user = user,
product = product,
status = FavoriteStatus.activate.value
)
else:
favorite = favorite[0]
if favorite.status == FavoriteStatus.activate.value:
favorite.status = FavoriteStatus.deactivate.value
else:
favorite.status = FavoriteStatus.activate.value
favorite.save()
return R.ok({"status":favorite.status})
再来是个别商品的部分:
if request.method == "GET" and productID:
req = request.GET
if "username" not in req:
return R.badRequest("username does not exist")
username = req["username"]
user = User.objects.filter(name = username)
if not user:
return R.badRequest("User not found")
user = user[0]
product = Product.objects.filter(id = productID)
if not product:
return R.badRequest("Product does not exist")
product = product[0]
favorite = Favorite.objects.filter(user = user).filter(product = product)
data = {
"status":0
}
if favorite:
data["status"] = favorite[0].status
return R.ok(data)
再来是前端的部分,到apis资料夹当中新增favorite.js,并且新增加载商品按赞状态跟按赞的API:
import { host,port } from '@/apis/constant.js'
import axios from 'axios'
export function getProductFavorite(pid,token,username){
return axios.get(`http://${host()}:${port()}/favorite/${pid}`,{
params:{
"username":username
},
headers:{
"AUTHORIZATION":token
}
})
}
export function addFavorite(pid,token,username){
return axios.post(`http://${host()}:${port()}/favorite`,{
"username":username,
"pid":pid
},{
headers:{
"AUTHORIZATION":token
}
})
}
到productDetail中新增按赞按纽:
<b-button variant="info">
{{ favoriteText }}
</b-button>
并在created方法当中新增获取商品按赞状态的程序码:
var token = window.localStorage.getItem("token")
var username = window.localStorage.getItem("username")
if(token == null || username == null){
this.favoriteText = "登入以按赞"
}else{
getProductFavorite(pid,token,username).then((response) => {
if(response.data.code == STATUS_OK){
var status = response.data.data.status
this.favoriteText = status == 0 ? "按赞" : "已按赞"
}
})
}
接着在按赞按钮上新增onclick function:
<b-button variant="info" @click="addToFavorite">
{{ favoriteText }}
</b-button>
并且新增addToFavorite方法,打後端的按赞API,并且根据状态显示不同按钮文字:
addToFavorite(){
var pid = this.$route.params.pid
var username = window.localStorage.getItem("username")
var token = window.localStorage.getItem("token")
if(username == null || token == null){
this.$fire({type:"error",text:"请登入!"}).then(() => {
location.href = "/#/login"
})
}else{
addFavorite(pid,token,username).then((response) => {
if(response.data.code == STATUS_OK){
this.favoriteText = response.data.data.status == 0 ? "按赞" : "已按赞"
}
})
}
},
就可以测试看看是否可以按赞了:
接下来是按赞好物的部分,在headers当中新增:
<b-nav-item-dropdown text="会员" right>
<b-dropdown-item href="/#/login" v-show="!isLogin">登入</b-dropdown-item>
<b-dropdown-item href="/#/register" v-show="!isLogin">注册</b-dropdown-item>
<b-dropdown-item href="/#/self" v-show="isLogin">个人资料</b-dropdown-item>
<b-dropdown-item href="/#/favorite" v-show="isLogin">按赞好物</b-dropdown-item>
<b-dropdown-item href="/#/order" v-show="isLogin">订单</b-dropdown-item>
<b-dropdown-item v-show="isLogin" @click="logout">登出</b-dropdown-item>
</b-nav-item-dropdown>
另外新增components\favorite.vue,做出模板:
<template>
<html lang="zh-Hant-TW">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" type="image/x-con" href="@/assets/favicon.ico">
<div id="app">
<headerComponent></headerComponent>
<div id="favoriteHeader" style="width:100%;height:100px;background-image: linear-gradient(to right,#C9C9C9,#F2FFFF,#00E6E6);padding-top: 40px;">
<h3>按赞好物</h3>
</div>
<b-row>
<b-col cols="2" v-for="item in items" :key="item.id" style="margin: 20px;border:1px solid #5B5B5B;padding: 10px;text-align: center;box-shadow:3px 3px 12px #4F4F4F;border-radius: 30px;">
<a :href="'/#/productDetail/' + item.product.id">
<img :src="'http://localhost:8000' + item.product.img" alt="" style="width: 200px;height: 200px;">
</a>
<h4 class="productTitle">
{{ item.product.name }}
</h4>
<h5 class="productPrice">
{{ item.product.price }}
</h5>
<div>
<b-button variant="danger" @click="cancel(item.product.id)">
取消按赞
</b-button>
</div>
</b-col>
</b-row>
</div>
</html>
</template>
<script>
export default{
name: "favoritePage",
components:{
'headerComponent':() => import('@/components/header.vue')
},
data(){
return {
items:[
{
"id":1,
"username":"admin123",
"product":{
"id":3,
"name":"耳机",
"price":123,
"stored_amount":12,
"img":"/media/productImage/airpod.png"
}
}
]
}
},
methods:{
cancel(data){
console.log(data)
}
}
}
</script>
呈现出来的页面:
在favorite.js当中新增getAllFavorite方法:
export function getAllFavorite(username,token){
return axios.get(`http://${host()}:${port()}/favorite`,{
"username":username
},{
headers:{
"AUTHORIZATION":token
}
})
}
并新增created方法,使用getAllFavorite方法取得资料:
created(){
var token = window.localStorage.getItem("token")
var username = window.localStorage.getItem("username")
if(token == null || username == null){
this.$fire({type:"error",text:"请登入"}).then(() => {
location.href = "/#/login"
})
}
getAllFavorite(username,token).then((response) => {
if(response.data.code == STATUS_OK){
this.items = response.data.data
}else{
this.$fire({type:"error",text:response.data.data})
}
})
},
接着新增取消方法,这里使用的是在商品详情页面用过的addFavorite API,让後端自动判定状态:
cancel(data){
var token = window.localStorage.getItem("token")
var username = window.localStorage.getItem("username")
var pid = data
addFavorite(pid,token,username).then((response) => {
if(response.data.code == STATUS_OK){
this.items.forEach((item,index) => {
if(item.product.id == pid){
this.items.splice(index,1)
}
})
}
})
}
即可测试是否可以按赞跟收回,还有取消後会不会从按赞好物清单中消失。
================================◉‿◉=================================
Day28结束了!在今天我们完成了按赞跟取消按赞还有收藏的机制,而明天我们将加上像是Facebook分享、Line分享的按纽,See ya next day!
<<: Day27 Router useParams 小实作
>>: Log Agent - Fluent Bit Input元件 与 Tail浅谈
接下来就是我要将测试放入现在正在进行的api中了 在这次的测试中,我想测试mRequest.Get(...
复习 透过 nmap 扫描 port 利用版本查询已知漏洞 透过人家撰写好 exploit 进行攻击...
Progressive Web App (PWA) 使用当下最新潮的 Web API,Progres...
打开 terminal ( command + space )输入以下指令安装 CocoaPods...
JIT、JIT 的叫了这麽多天,终於就是今天了! 今天就是要来讲解 JIT 模式哦~~ JIT 模...