专题:Vue+Django REST framework前后端分离生鲜电商
Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。
Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket ;
Django版本:2.2、djangorestframework:3.9.2。
更多内容请点击 我的博客 查看,欢迎来访。
用户留言功能
留言分为以上5中类型,支持上传文件。
现有的留言models如下,需要的字段都是齐全的
class UserLeavingMessage(models.Model):
"""
用户留言
"""
MESSAGE_TYPE = (
(1, '留言'),
(2, '投诉'),
(3, '询问'),
(4, '售后'),
(5, '求购')
)
user = models.ForeignKey(User, verbose_name='用户', help_text='用户', on_delete=models.CASCADE, related_name='leaving_msgs')
message_type = models.IntegerField(default=1, choices=MESSAGE_TYPE, verbose_name='留言类型', help_text='留言类型:1-留言,2-投诉, 3-询问, 4-售后, 5-求购')
subject = models.CharField(max_length=100, default='', verbose_name='主题', help_text='主题')
message = models.TextField(default='', verbose_name='留言内容', help_text='留言内容')
file = models.FileField(upload_to='upload/leaving_msg/', blank=True, null=True, verbose_name='上传文件', help_text='上传文件')
add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')
class Meta:
verbose_name_plural = verbose_name = '用户留言'
def __str__(self):
return '{} {}:{}'.format(self.user.name if self.user.name else self.user.username, self.get_message_type_display(), self.subject)
序列化用户留言UserLeavingMessageSerializer
在 apps/user_operation/serializers.py 添加一个 UserLeavingMessageSerializer
用于序列化用户留言
from .models import UserFav, UserLeavingMessage
class UserLeavingMessageSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault() # 表示user为隐藏字段,默认为获取当前登录用户
)
class Meta:
model = UserLeavingMessage
fields = ['user', 'message_type', 'subject', 'message', 'file', 'add_time']
用户留言功能视图UserLeavingMessageViewSet
首先引入该models和serializer
from .serializers import UserFavSerializer, UserFavListSerializer, UserLeavingMessageSerializer
from .models import UserFav, UserLeavingMessage
class UserLeavingMessageViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
"""
create:
创建用户留言
list:
获取用户留言
delete:
删除用户留言
"""
queryset = UserLeavingMessage.objects.all()
serializer_class = UserLeavingMessageSerializer
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) # 用户必须登录才能访问
authentication_classes = (JWTAuthentication, SessionAuthentication) # 配置登录认证:支持JWT认证和DRF基本认证
def get_queryset(self):
"""只查询当前登录用户"""
return self.queryset.filter(user=self.request.user)
注册用户留言url
修改 DjangoOnlineFreshSupermarket/urls.py 添加router
from user_operation.views import UserFavViewSet, UserLeavingMessageViewSet
# ......
router.register(r'livingmsgs', UserLeavingMessageViewSet, base_name='livingmsgs') # 用户留言
访问 http://127.0.0.1:8000/docs/#livingmsgs-list 后台文档,可以看到留言的三个功能
因为必须要在登录状态下,可以选择session去认证
但是创建留言并没有上传文件的功能,这儿选择DRF Api来完成
访问 http://127.0.0.1:8000/livingmsgs/ 可以看到下面的内容
Vue中显示用户留言
留言组件在 src/views/member/message.vue 中,当组件创建时
created() {
this.getMessage();
},
调用getMessage()
函数
getMessage() { //获取留言
getMessages().then((response) => {
console.log(response.data);
this.messageAll = response.data;
}).catch(function (error) {
console.log(error);
});
},
通过api src/api/api.js 请求后端
//获取留言
export const getMessages = () => {
return axios.get(`${local_host}/livingmsgs/`)
};
//添加留言
export const addMessage = params => {
return axios.post(`${local_host}/livingmsgs/`, params, {headers: {'Content-Type': 'multipart/form-data'}})
};
//删除留言
export const delMessages = messageId => {
return axios.delete(`${local_host}/livingmsgs/` + messageId + '/')
};
src/views/member/message.vue 将请求结果展示出来
留言:
投诉:
询问:
售后:
求购:
{{item.subject}}
({{item.add_time}})
{{item.message}}
DRF Api中测试留言上传文件
访问 http://127.0.0.1:8000/livingmsgs/ 添加留言同时上传文件
然后点击POST提交,可以看到返回的数据
其中包括file
字段,里面是文件的完整路径
再次访问 http://127.0.0.1:8000/livingmsgs/ 可以查看它的get请求
其中file
也是完整的url
前端访问 http://127.0.0.1:8080/#/app/home/member/message
点击“查看上传的文件”可以看到会自动跳转到文件浏览。
格式化显示日期时间
但是这个时间显示太丑了,进行格式化
修改 apps/user_operation/serializers.py 中的UserLeavingMessageSerializer
,指定add_time
class UserLeavingMessageSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault() # 表示user为隐藏字段,默认为获取当前登录用户
)
add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M') # read_only序列化只返回不提交,format指定格式化
class Meta:
model = UserLeavingMessage
fields = ['user', 'message_type', 'subject', 'message', 'file', 'add_time']
访问 http://127.0.0.1:8000/livingmsgs/ 可以看到时间已被正常序列化
用户留言删除
在 src/views/member/message.vue 中删除用户留言需要给定该对象的id
删除
而在做序列化时并没有显示出来,现在修改 apps/user_operation/serializers.py 为UserLeavingMessageSerializer
添加id
字段
class UserLeavingMessageSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault() # 表示user为隐藏字段,默认为获取当前登录用户
)
class Meta:
model = UserLeavingMessage
fields = ['id', 'user', 'message_type', 'subject', 'message', 'file', 'add_time']
可以看到id
已被显示出来
访问 http://127.0.0.1:8080/#/app/home/member/message 点击某一条留言的“删除”
该留言就直接被删除了。
删除功能在 src/views/member/message.vue 中
deleteMessage(index, id) { // 删除留言
delMessages(id).then((response) => {
alert("删除成功");
this.messageAll.splice(index, 1);
}).catch(function (error) {
console.log(error);
});
},
用户留言创建
创建留言的表单在 src/views/member/message.vue
当用户点击“提交”,会调用submitMessage
函数
preview(e) {
this.file = e.target.files[0]; //获取文件资源
console.log(this.file);
},
submitMessage() { //提交留言
const formData = new FormData();
formData.append('file', this.file);
formData.append('subject', this.subject);
formData.append('message', this.message);
formData.append('message_type', this.message_type);
addMessage(formData).then((response) => {
this.getMessage();
}).catch(function (error) {
console.log(error);
});
},
获取表单保存在formData
中,addMessage
提交到后端
也就是直接调用 src/api/api.js 中的addMessage
//添加留言
export const addMessage = params => {
return axios.post(`${local_host}/livingmsgs/`, params, {headers: {'Content-Type': 'multipart/form-data'}})
};
上传文件测试
为什么DRF支持这么轻松的上传文件?
在DRF Api https://www.django-rest-framework.org/api-guide/parsers/#multipartparser 中可以看到
解析多部分HTML表单内容,支持文件上传。request.data
都将被一个 QueryDict
填充。
你通常会同时使用FormParser
和MultiPartParser
两者,以便完全支持HTML表单数据。
.media_type: multipart/form-data