什么事频道组?什么是无限级分类?、
频道组:按照一个顶级类别进行区分,相同的事务的集合组
无限级分类:一个类可以分成多个子类,然后一个子类又可以分另外多个子类这样无限分下去的方法。
创建模型类
在项目goods子应用下的models.py文件中进行创建
#商品种类表
class Cate(models.Model):
name=models.CharField('种类名称',max_length=30)
#自关联 #反向查询可以直接调用'subs'
cid=models.ForeignKey('self',on_delete=models.CASCADE,related_name='subs',null=True,blank=True)
def __str__(self):
return self.name
class Meta:
db_table='goodscate'
verbose_name_plural='商品种类表'
# 分类分组(频道组)
class Group(models.Model):
name=models.CharField('频道组名称',max_length=30)
# #一对一关系
cate=models.OneToOneField(Cate,on_delete=models.CASCADE,verbose_name='一级类别')
group_url=models.CharField('频道的地址',max_length=100,default='http://jd.com') #默认
sequence=models.IntegerField('展示顺序',default=0)
def __str__(self):
return self.name
class Meta:
db_table='cate_group'
verbose_name_plural='频道组'
生成迁移文件,进行迁移
对商品种类表cate导入数据
根据导入的数据自行给分类分组(频道组)Group手动添加几条数据
注:填写一级类别的数据
编写序列化器
在子应用目录下创建serializers.py文件进行配置
from rest_framework import serializers
from .models import *
# 分类分组(频道组)的序列化器
class GroupSer(serializers.ModelSerializer):
# #只序列化输出
cate_name=serializers.SerializerMethodField(read_only=True)
def get_cate_name(self,obj):
return obj.cate.name
class Meta:
model=Group
fields='__all__'
read_only_fields=['id']
#商品类别的序列化器
class GoodsCateSer(serializers.ModelSerializer):
class Meta:
model=Cate
fields='__all__'
read_only_fields=['id']
编写视图类
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView,ListAPIView
from .serializers import *
from .models import *
from rest_framework.pagination import PageNumberPagination
#分页器类
class MyPagination2(PageNumberPagination):
page_size = 2
max_page_size = 5
page_query_param = 'page'
page_size_query_param = 'pageSize'
#频道组的视图
class ListCreateGroupAPIView(ListCreateAPIView):
queryset = Group.objects.all()
serializer_class = GroupSer
pagination_class = MyPagination2
class ReUpDeAPIViwe(RetrieveUpdateDestroyAPIView):
queryset = Group.objects.all()
serializer_class = GroupSer
lookup_field = 'pk'
lookup_url_kwarg = 'pk'
#一级类别的视图 #用于前端获取外键数据
class FirstCateAPIView(ListAPIView):
queryset = Cate.objects.filter(cid=None)
serializer_class = GoodsCateSer
配置路由
from django.urls import path
from .views import *
urlpatterns = [
#频道组的接口,获取所有、新增一个
path('channels/',ListCreateGroupAPIView.as_view()),
#频道组的接口,检索,更改,删除
path('channels/<int:pk>/',ReUpDeAPIViwe.as_view()),
#加载所有的一级类别
path('channels/firstcates/',FirstCateAPIView.as_view())
]
前端
找到对应的前端项目中对应的vue组件
对相对的功能进行配置
例如:Channels.vue
配置数据分页
<script>
import BreadCrumb from "@/components/widget/BreadCrumb";
// 添加频道组
import Addchannels from "@/components/widget/AddChannels";
// 展示,删除,修改
import ChannelsTable from "@/components/widget/ChannelsTable";
export default {
name: "Channels",
data() {
return {
page: 1,
total: 0,
pagesize: 2,
aChannelsList: [],
};
},
components: {
BreadCrumb,
Addchannels,
ChannelsTable,
},
mounted() {
this.fnGetData(1);
},
methods: {
// 获取数据
fnGetData(num) {
this.axios
.get("/v1/goods/channels/", {
params: {
page: num,
pageSize: this.pageSize,
},
headers: {
Authorization: "JWT " + localStorage.token,
},
responseType: "json",
})
.then((result) => {
this.aChannelsList = result.data.results;
this.total=result.data.count
})
.catch((err) => {
console.log("频道请求的错误", err);
});
},
fnGetPage(page){
this.page=page
this.fnGetData(page)
}
},
};
</script>
展示,修改,删除频道组数据
例如:ChannelsTable.vue
表单修改时下拉框实现选择类别内容
<script>
let token = localStorage.token;
export default {
name: 'OptionsTable',
props:['channels'],
data () {
return {
pop_show:false,
group_type_list:[],
category_list:[],
ChannelsForm:{
cate:'',
group_url:'',
name:'',
sequence:'',
},
rulesChannelsForm:{}
}
},
methods:{
// 点击编辑时触发的方法
fnPopShow(id){
// this.pop_show 默认时false
this.pop_show = true;
this.edit_id = id;
this.axios.get('/v1/goods/channels/'+this.edit_id+'/', {
headers: {
'Authorization': 'JWT ' + token
},
responseType: 'json',
})
.then(res=>{
console.log('更新一个频道组的响应',res);
this.ChannelsForm.name = res.data.name;
this.ChannelsForm.group_url = res.data.group_url;
this.ChannelsForm.sequence = res.data.sequence;
this.ChannelsForm.cate = res.data.cate
}).catch(err=>{
console.log(err.response);
});
},
// 提交
submitForm(){
this.axios.put('/v1/goods/channels/'+this.edit_id+'/', this.ChannelsForm, {
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.resetForm('ChannelsForm');
this.$emit('fnResetTable');
}else{
this.$message({
type: 'error',
message: '频道修改失败!'
});
}
}).catch(err=>{
console.log(err.response);
})
},
// 删除
fnDelChannel(id){
this.edit_id = id;
this.$confirm('此操作将删除该频道, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.axios.delete('/v1/goods/channels/'+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: '已取消删除'
});
});
},
// 获取所有的类别
fnGetCategories(){
this.axios.get('/v1/goods/channels/firstcates/', {
headers: {
'Authorization': 'JWT ' + token
},
responseType: 'json',
})
.then(res=>{
this.category_list = res.data;
console.log("类别>>>",this.category_list)
}).catch(err=>{
console.log(err.response);
});
},
resetForm(formName){
this.$refs[formName].resetFields();
}
},
mounted(){
// 获取类被组
// this.fnGetChannelType();
// 获取所有的一级类别信息
this.fnGetCategories();
}
}
</script>
添加数据
例如:AddChannels.vue
添加时表单也可以使用下拉框选择绑定类别,同理如上
<script>
// import cons from "@/components/constant";
let token = localStorage.token;
export default {
name: "AddChannels",
data() {
return {
pop_show: false,
group_type_list: [],
category_list:[],
ChannelsForm: {
name: "",
cate: "",
group_url: "",
sequence: "",
},
rulesChannelsForm: {},
};
},
methods: {
// 提交的数据
submitForm() {
this.axios.post('/v1/goods/channels/',this.ChannelsForm,{
headers:{
Authorization:'JWT'+localStorage.token
},
responsetype:'json'
}).then((result) => {
console.log('更改成功的响应',result)
if (result.status==201){
this.$message({
type:'success',
message:'添加成功'
})
//隐藏对话框
this.pop_show=false
this.$refs['channelsForm'].restFields()
this.$emit('fnResetTable')
}else{
this.$message({
type:'error',
message:'添加成功'
})
}
}).catch((err) => {
console.log('修改失败的响应'+err)
});
},
// 类别组数据
fnGetChannelType() {
this.axios.get('/v1/goods/channels/firstcates/',{
headers:{
Authorization:'JWT'+localStorage.token
},
responseType:'json'
}).then((result) => {
console.log('获取一级类别的响应'+result)
this.category_list=result.data
}).catch((err) => {
console.log('获取以及类别失败的响应'+err)
});
},
},
// 挂载
mounted() {
this.fnGetChannelType();
},
};
</script>