后端
创建模型类
外键绑定sku商品表
#商品图片的模型类
class SKUImage(models.Model):
sku=models.ForeignKey(SKUS,on_delete=models.CASCADE,verbose_name='商品')
image=models.CharField('商品图片',max_length=300)
def __str__(self):
return f'商品名称{self.sku.name},商品地址{self.image}'
class Meta:
db_table='sku_image'
verbose_name_plural='商品图片'
编写序列化器
#SKUImage模型类的序列化器
class SKUImageSer(serializers.ModelSerializer):
sku_name=serializers.SerializerMethodField(read_only=True)
def get_sku_name(self,obj):
return obj.sku.name
class Meta:
model=SKUImage
fields='__all__'
read_only_fields=['id']
编写序列化器
需要写一个上传图片的视图
SKUImage视图集要重写create方法
from rest_framework_jwt.utils import jwt_decode_handler
#上传图片的视图
class UploadSKUImageAPIView(APIView):
def post(self,request):
# 1.接收前端的数据
token=request.data.get('token')
file=request.data.get('file')
#2.验证token,是否认证
try:
payload=jwt_decode_handler(token)
except:
return Response({'code':401,'msg':'未认证'},status=401)
#3.处理图片的上传,保存图片
#/static/images/goods/xxx.jpg
static_path='static/image/goods'
file_path=os.path.join(settings.BASE_DIR,static_path)
#判断file_path 目录是否存在,不存在则创建
if not os.path.exists(file_path):
os.makedirs(file_path)
#图片名称
image_name=os.path.join(file_path,file.name)
#4.存储图片
with open(image_name,'wb')as f:
f.write(file.file.read())
# 5.返回响应
return Response({'code':200,'msg':'上传成功','static_path':static_path})
# skuImage的视图集
class SKUImageViewSet(ModelViewSet):
queryset = SKUImage.objects.all()
serializer_class = SKUImageSer
lookup_field = 'pk'
lookup_url_kwarg = 'pk'
pagination_class = MyPagination
#重写create 实现去重机制
def create(self, request, *args, **kwargs):
#1.接收前段数据
sku_id=request.data.get('sku')
image=request.data.get('image')
print('前端传的数据:',sku_id,image)
#2.判断当前商品sku_id 有没有添加image这张图片
sku_image=SKUImage.objects.filter(sku_id=sku_id,image=image)
if sku_image:
# 说明已经添加
return Response({
'code':400,
'msg':'该商品已经添加该图片'
})
#3.未添加时,正常添加图片
obj=SKUImage.objects.create(sku_id=sku_id,image=image)
return Response({
'code':200,
'msg':'添加图片成功',
'data':self.get_serializer(obj).data
})
配置路由
from django.urls import path
from rest_framework import routers
from .views import *
urlpatterns = [
#上传商品图片的接口
path('upload/skuImage/',UploadSKUImageAPIView.as_view())
]
#品牌的路由
router=routers.SimpleRouter()
router.register('skus',SKUAPIView,'skus') #sku的路由
router.register('specOption',SpecOptionViewSet,'specOption') #规格选项路由
router.register('skuImage',SKUImageViewSet,'skuImage') #
urlpatterns+=router.urls
前端
找到对应的veu组件,进行配置
实现sku的增删改查
例如:Pictures.vue 获取全部数据
<script>
import BreadCrumb from '@/components/widget/BreadCrumb'
//对商品图片要进行添加
import Addpictures from '@/components/widget/AddPictures'
// 展示 删除 修改商品图片
import PicturesTable from '@/components/widget/PicturesTable'
export default {
name: 'Brands',
data () {
return {
page:1,
total:0,
pagesize:3,
aPicturesList:[]
}
},
components:{
BreadCrumb,
Addpictures,
PicturesTable
},
mounted(){
this.fnGetData(1);
},
methods:{
fnGetData(num){
this.axios.get('/v1/goods/skuImage/',{
params:{
page:num?num:this.page,
pageSize:this.pagesize
},
headers:{
Authorization:'JWT '+localStorage.token
},
responseType:'json'
}).then((result) => {
this.aPicturesList=result.data.results
this.total=result.data.count
}).catch((err) => {
console.log('加载sku图片错误',err)
});
},
fnGetPage(num){
this.page=num
this.fnGetData(num)
}
}
}
</script>
例如:PicturesTable.vue进行展示修改数据
修改事件中的路由,字段等
<script>
let token = localStorage.token;
export default {
name: "OptionsTable",
props: ["pictures"],
data() {
return {
host:'http://127.0.0.1:8000', //展示图片的时候加上去
uploaData: {
token: "",
},
// 外链地址
baseUrl: "http://r8isbvnn5.bkt.clouddn.com/",
pop_show: false,
sku_list: [],
PicturesForm: {
sku: "",
image: "",
},
rulesPicturesForm: {},
};
},
methods: {
//点击编辑触发
fnPopShow(id) {
this.pop_show = true;
this.edit_id = id;
this.axios
.get("/v1/goods/skuImage/" + this.edit_id + "/", {
headers: {
Authorization: "JWT " + token,
},
responseType: "json",
})
.then((res) => {
this.PicturesForm.sku = res.data.sku;
this.PicturesForm.image = res.data.image;
})
.catch((err) => {
console.log('修改错误',err.response);
});
},
//更新的提交
submitForm() {
this.axios
.put("/v1/goods/skuImage/" + this.edit_id + "/", this.PicturesForm, {
headers: {
Authorization: "JWT " + token,
},
responseType: "json",
})
.then((res) => {
console.log("修改的响应》》", res);
if (res.status==200){
this.$message({
type: "success",
message: "商品图片修改成功!",
});
this.pop_show = false;
this.$emit("fnResetTable");
this.resetForm("PicturesForm");
}else{
this.$message({
type: "error",
message: "商品图片修改失败!",
});
}
})
.catch((err) => {
console.log(err.message);
});
},
fnDelPictures(id) {
this.edit_id = id;
this.$confirm("此操作将删除该商品图片, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.axios
.delete("/v1/goods/skuImage/" + this.edit_id + "/", {
headers: {
Authorization: "JWT " + token,
},
responseType: "json",
})
.then((res) => {
if (res.status==204){
this.$message({
type: "success",
message: "删除图片成功!",
});
this.$emit("fnResetTable");
}else{
this.$message({
type: "error",
message: "删除图片失败!",
});
}
})
.catch((err) => {
if (err.response.status == 404) {
this.$message({
type: "info",
message: "图片未找到!",
});
}
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除",
});
});
},
// 加载所有的sku
fnGetSkuList() {
this.axios
.get("/v1/goods/skus/", {
headers: {
Authorization: "JWT " + token,
},
responseType: "json",
})
.then((res) => {
console.log('加载所有的sku',res);
this.sku_list = res.data;
})
.catch((err) => {
console.log(err.response);
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
// 点击上传,上传成功触发的方法
uploadSuccess(res, files, fiels_list) {
// res.key 获取上传的图片在七牛云存放的地址
// 拼接图片地址
console.log("更新图片的上传", res,files);
// this.imgUrl = this.baseUrl + res.key;
this.PicturesForm.image='/'+res.static_path+'/'+files.name
},
uploadError(err) {
console.log('上传失败',err);
},
},
mounted() {
this.fnGetSkuList();
this.uploaData.token=localStorage.token
},
};
</script>
例如:AddPictures.vue进行修改数据
修改事件中的路由,字段等
添加绑定外键的字段实现下拉框添加
添加跟修改获取数据类似
<script>
let token = localStorage.token;
export default {
name: "AddChannels",
data() {
return {
host:'http://localhost:8000',
pop_show: false,
baseUrl: "http://r8isbvnn5.bkt.clouddn.com/",
imgUrl: "",
uploadData: {
token: "",
},
sku_list: [],
PicturesForm: {
sku: "",
image: "",
},
rulesBrandsForm: {
sku:[{required:true,message:'必输入sku'}],
image:[{required:true,message:'必输入image'}]
},
};
},
methods: {
// 提交
submitForm() {
//校验数据
this.$refs['PicturesForm'].validate((val)=>{
if(val){
this.axios
.post("/v1/goods/skuImage/", this.PicturesForm, {
headers: {
Authorization: "JWT " + token,
// "Content-Type": "multipart/form-data",
},
responseType: "json",
})
.then((res) => {
console.log('添加商品图片',res);
if (res.data.code == 200) {
this.$message({
type: "success",
message: "图片添加成功!",
});
this.pop_show = false;
this.resetForm("PicturesForm");
this.$emit("fnResetTable");
}else{
this.$message({
type:'error',
message:res.data.msg
})
}
})
.catch((err) => {
console.log(err.response);
});
}else{
return false
}
})
},
// 获取所有的sku
fnGetSkuList() {
this.axios
.get("/v1/goods/skus/", {
headers: {
Authorization: "JWT " + token,
},
responseType: "json",
})
.then((res) => {
console.log('加载所有的sku商品',res);
this.sku_list = res.data;
})
.catch((err) => {
console.log(err.response);
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
// 点击上传,上传成功触发的方法
uploadSuccess(res, files) {
console.log("上传成功", res,files);
// 拼接图片地址
// this.imgUrl = this.baseUrl + res.key;
this.PicturesForm.image='/'+res.static_path+'/'+files.name
},
uploadError(err) {
console.log('上传失败:',err);
},
},
mounted() {
this.uploadData.token=localStorage.token
//获取所有的sku商品
this.fnGetSkuList();
},
};
</script>