您现在的位置是: 网站首页 >Django >Vue+Django REST framework前后端分离生鲜电商 Django

【Vue+DRF生鲜电商】23.个人中心用户留言功能

admin2019年6月19日 14:11 Django | Html | Vue 266人已围观

Vue+Django REST framework前后端分离生鲜电商简介 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。 Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket ; Django版本:2.2、djangorestframework:3.9.2。 前端Vue模板可以直接联系我拿。

## 用户留言功能 ![BLOG_20190619_141603_61](/media/blog/images/2019/06/BLOG_20190619_141603_61.png "博客图集BLOG_20190619_141603_61.png") 留言分为以上5中类型,支持上传文件。 现有的留言models如下,需要的字段都是齐全的 ```python 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` 用于序列化用户留言 ```python 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 ```python 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 ```python from user_operation.views import UserFavViewSet, UserLeavingMessageViewSet # ...... router.register(r'livingmsgs', UserLeavingMessageViewSet, base_name='livingmsgs') # 用户留言 ``` 访问 http://127.0.0.1:8000/docs/#livingmsgs-list 后台文档,可以看到留言的三个功能 ![BLOG_20190619_141551_80](/media/blog/images/2019/06/BLOG_20190619_141551_80.png "博客图集BLOG_20190619_141551_80.png") 因为必须要在登录状态下,可以选择session去认证 ![BLOG_20190619_141546_89](/media/blog/images/2019/06/BLOG_20190619_141546_89.png "博客图集BLOG_20190619_141546_89.png") 但是创建留言并没有上传文件的功能,这儿选择DRF Api来完成 访问 http://127.0.0.1:8000/livingmsgs/ 可以看到下面的内容 ![BLOG_20190619_141539_37](/media/blog/images/2019/06/BLOG_20190619_141539_37.png "博客图集BLOG_20190619_141539_37.png") ### Vue中显示用户留言 留言组件在 src/views/member/message.vue 中,当组件创建时 ```JavaScript created() { this.getMessage(); }, ``` 调用`getMessage()`函数 ```JavaScript getMessage() { //获取留言 getMessages().then((response) => { console.log(response.data); this.messageAll = response.data; }).catch(function (error) { console.log(error); }); }, ``` 通过api src/api/api.js 请求后端 ```JavaScript //获取留言 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 将请求结果展示出来 ```html <li v-for="(item,index) in messageAll"> <div> <span v-if="item.message_type===1">留言:</span> <span v-if="item.message_type===2">投诉:</span> <span v-if="item.message_type===3">询问:</span> <span v-if="item.message_type===4">售后:</span> <span v-if="item.message_type===5">求购:</span> <span>{{item.subject}}</span> <span>({{item.add_time}})</span> </div> <div> {{item.message}} </div> <div> <a @click="deleteMessage(index, item.id)">删除</a> <a :href="(item.file)">查看上传的文件</a> </div> </li> ``` ![BLOG_20190619_141528_67](/media/blog/images/2019/06/BLOG_20190619_141528_67.png "博客图集BLOG_20190619_141528_67.png") ### DRF Api中测试留言上传文件 访问 http://127.0.0.1:8000/livingmsgs/ 添加留言同时上传文件 ![BLOG_20190619_141520_68](/media/blog/images/2019/06/BLOG_20190619_141520_68.png "博客图集BLOG_20190619_141520_68.png") 然后点击POST提交,可以看到返回的数据 ![BLOG_20190619_141504_82](/media/blog/images/2019/06/BLOG_20190619_141504_82.png "博客图集BLOG_20190619_141504_82.png") 其中包括`file`字段,里面是文件的完整路径 再次访问 http://127.0.0.1:8000/livingmsgs/ 可以查看它的get请求 ![BLOG_20190619_141439_85](/media/blog/images/2019/06/BLOG_20190619_141439_85.png "博客图集BLOG_20190619_141439_85.png") 其中`file`也是完整的url 前端访问 http://127.0.0.1:8080/#/app/home/member/message ![BLOG_20190619_141432_19](/media/blog/images/2019/06/BLOG_20190619_141432_19.png "博客图集BLOG_20190619_141432_19.png") 点击“查看上传的文件”可以看到会自动跳转到文件浏览。 ### 格式化显示日期时间 但是这个时间显示太丑了,进行格式化 修改 apps/user_operation/serializers.py 中的`UserLeavingMessageSerializer`,指定`add_time` ```python 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/ 可以看到时间已被正常序列化 ![BLOG_20190619_141426_54](/media/blog/images/2019/06/BLOG_20190619_141426_54.png "博客图集BLOG_20190619_141426_54.png") ### 用户留言删除 在 src/views/member/message.vue 中删除用户留言需要给定该对象的id ```html <a @click="deleteMessage(index, item.id)">删除</a> ``` 而在做序列化时并没有显示出来,现在修改 apps/user_operation/serializers.py 为`UserLeavingMessageSerializer`添加`id`字段 ```python 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'] ``` ![BLOG_20190619_141417_12](/media/blog/images/2019/06/BLOG_20190619_141417_12.png "博客图集BLOG_20190619_141417_12.png") 可以看到`id`已被显示出来 访问 http://127.0.0.1:8080/#/app/home/member/message 点击某一条留言的“删除” ![BLOG_20190619_141412_11](/media/blog/images/2019/06/BLOG_20190619_141412_11.png "博客图集BLOG_20190619_141412_11.png") 该留言就直接被删除了。 删除功能在 src/views/member/message.vue 中 ```JavaScript deleteMessage(index, id) { // 删除留言 delMessages(id).then((response) => { alert("删除成功"); this.messageAll.splice(index, 1); }).catch(function (error) { console.log(error); }); }, ``` ### 用户留言创建 创建留言的表单在 src/views/member/message.vue ```html <form action="" method="post" enctype="multipart/form-data" name="formMsg"> <table width="100%" border="0" cellpadding="3"> <tbody> <tr> <td align="right">留言类型:</td> <td> <input type="radio" id="one" value="1" v-model="message_type"> <label for="one">留言</label> <input type="radio" id="two" value="2" v-model="message_type"> <label for="two">投诉</label> <input type="radio" id="three" value="3" v-model="message_type"> <label for="three">询问</label> <input type="radio" id="four" value="4" v-model="message_type"> <label for="four">售后</label> <input type="radio" id="five" value="5" v-model="message_type"> <label for="five">求购</label> </td> </tr> <tr> <td align="right">主题:</td> <td><input name="msg_title" type="text" size="30" class="inputBg" v-model="subject"></td> </tr> <tr> <td align="right" valign="top">留言内容:</td> <td><textarea name="msg_content" cols="50" rows="4" wrap="virtual" class="B_blue" v-model="message"></textarea></td> </tr> <tr> <td align="right">上传文件:</td> <td><input type="file" name="message_img" size="45" class="inputBg" @change="preview"></td> </tr> <tr> <td>&nbsp;</td> <td><input type="hidden" name="act" value="act_add_message"> <a class="btn_blue_1" @click="submitMessage">提交</a> </td> </tr> <tr> <td>&nbsp;</td> <td> <font color="red">小提示:</font><br> 您可以上传以下格式的文件:<br>gif、jpg、png、word、excel、txt、zip、ppt、pdf </td> </tr> </tbody> </table> </form> ``` ![BLOG_20190619_141404_10](/media/blog/images/2019/06/BLOG_20190619_141404_10.png "博客图集BLOG_20190619_141404_10.png") 当用户点击“提交”,会调用`submitMessage`函数 ```JavaScript 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` ```JavaScript //添加留言 export const addMessage = params => { return axios.post(`${local_host}/livingmsgs/`, params, {headers: {'Content-Type': 'multipart/form-data'}}) }; ``` 上传文件测试 ![BLOG_20190619_141355_93](/media/blog/images/2019/06/BLOG_20190619_141355_93.png "博客图集BLOG_20190619_141355_93.png") ![BLOG_20190619_141349_84](/media/blog/images/2019/06/BLOG_20190619_141349_84.png "博客图集BLOG_20190619_141349_84.png") 为什么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`

很赞哦! (0)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行590天
  • 系统信息:Linux
  • 后台程序:Python: 3.6.6
  • 网站框架:Django: 2.2.9
  • 文章统计:222 篇
  • 文章评论:40 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 微信公众号:扫描二维码,关注我们
返回
顶部
标题 换行 登录
网站