Vue+Django REST framework
Using Python 3.6 and Django 2.0.2 (Django-rest-framework) and front-end vue to develop front-end and back-end separated mall website
The project supports Alipay payment (temporarily does not support WeChat payment), supports mobile phone SMS verification code registration, supports third party login. sentry error monitoring system is integrated.
Online demo address: http://vueshop.mtianyan.cn/
github source code address: https://github.com/mtianyan/VueDjangoFrameWorkShop
Content of this section: vue and user interface information debugging
vue and user interface information coordination
vue's Personal Center Data Details Component
src/views/member/userinfo.vue
Data loading must be in the create method.
created () { this.getUserInfo(); },
Called the getUserInfo method
getUserInfo () { //Request user information getUserDetail().then((response)=> { this.userInfo = response.data; }).catch(function (error) { console.log(error); }); },
Call the getUserDeatil interface, and then fill in the data of the response data as Userinfo.
//Getting User Information export const getUserDetail = () => { return axios.get(`${host}/users/1/`) }
Change host to localhost
User Personal Information Modification
Configure update mixins for UserViewset
This carries the operation of updating and partial updating.
It accepts put and patch requests. Put is actually an update operation, and patch is a partial update.
class UserViewset(CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
Logic in vue
<button class="btn_blue_1" style="border:none;" @click="confirmModify">Confirm revision</button>
Verify that the modification calls the confirmModify method.
confirmModify () { // Confirm revision updateUserInfo(this.userInfo).then((response)=> { alert('Modified success'); }).catch(function (error) { console.log(error); }); }
This calls the interface updateUserInfo
//Modify user information export const updateUserInfo = params => { return axios.patch(`${host}/users/1/`, params) }
Change host to localhost
The user username has been updated to be Chinese random code. As well as modifying the user's name, identity authentication is invalid
User Collection Function
Our previous List modelmixin in UserFavViewSet has returned the id of goods and the id of this collection relationship. But what we need is information about goods, so in Serilizer
Add a Serializers
class UserFavDetailSerializer(serializers.ModelSerializer): # Get the product information through goods_id. Nested Serilizer is needed goods = GoodsSerializer() class Meta: model = UserFav fields = ("goods", "id")
Collection submission only needs to pass goods'id over, and user favdetail wants to get goods' details when it gets them.
Dynamic Serializer.
# Setting up dynamic Serializer def get_serializer_class(self): if self.action == "list": return UserFavDetailSerializer elif self.action == "create": return UserFavSerializer return UserFavSerializer
You can also write a separate Serilizer that returns only the brief information in the collection.
src/views/member/collection.vue:
Call getCollection when create
created () { this.getCollection(); },
The getcollection method takes the data returned by the getAllFavs interface and fills it in
getCollection () { //Get a collection list getAllFavs().then((response)=> { this.collections = response.data; }).catch(function (error) { console.log(error); }); },
Modify getallfav as the local interface
export const getAllFavs = () => { return axios.get(`${local_host}/userfavs/`) }
Delete operation:
<a class="f6" @click="deletePro(index, item.goods.id)">delete</a>
Delete operation calls deletePro and passes in index index and goods.id as parameters
deletePro (index, id) { //Delete Collected Goods alert('Are you sure you want to delete the selected item from your collection?'); delFav(id).then((response)=> { this.collections.splice(index,1); alert('Deleted goods'); }).catch(function (error) { console.log(error); }); }
splice deletes the data in vue, making the front page one less.
delfav deletes back-end database data.
//Cancel collection export const delFav = goodsId => { return axios.delete(`${local_host}/userfavs/`+goodsId+'/') }
User Message Function
Delete, get messages, add user messages. You can upload files in your message.
Background interface viewset and supporting Serilizer
user_operation/serializers.py:
class LeavingMessageSerializer(serializers.ModelSerializer): user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M') class Meta: model = UserLeavingMessage fields = ("user", "message_type", "subject", "message", "file", "id" ,"add_time")
The user gets the current user directly, and the add_time settings are readable and formatted.
class LeavingMessageViewset(mixins.ListModelMixin, mixins.DestroyModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet): """ list: //Getting User Messages create: //Add message delete: //Delete message function """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) serializer_class = LeavingMessageSerializer # You can only see your message def get_queryset(self): return UserLeavingMessage.objects.filter(user=self.request.user)
Return only the message of the current user
Configure a matching url
Implementation code:
# Configure the url for user messages router.register(r'messages', LeavingMessageViewset, base_name="messages")
When we delete, we need the id returned by the server. Front-end and back-end separated system, the server returns the full address can be directly viewed by the front-end.
addtime should only be returned without submitting. Fill in automatically by the current time obtained.
vue source interface
//Get messages export const getMessages = () => {return axios.get(`${host}/messages/`)} //Add message export const addMessage = params => {return axios.post(`${host}/messages/`, params, {headers:{ 'Content-Type': 'multipart/form-data' }})} //Delete message export const delMessages = messageId => {return axios.delete(`${host}/messages/`+messageId+'/')}
Change all host s to localhost
How to replace T in time with a space symbol? Add a format for add_time
How does the data filling mapping work? The component is src/views/member/message.vue
created () { this.getMessage(); },
Call getmessage() before component creation
getMessage () { //Get messages getMessages().then((response)=> { console.log(response.data); this.messageAll = response.data; }).catch(function (error) { console.log(error); }); },
//Get messages export const getMessages = () => {return axios.get(`${local_host}/messages/`)}
Get all messages and assign values to messageAll for filling
The if conditional mapping here should be consistent with our model
Deletion calls deleteMessage
<a @click="deleteMessage(index, item.id)">delete</a> deleteMessage (index, id) { // Delete message delMessages(id).then((response)=> { alert("Delete successful") this.messageAll.splice(index,1); }).catch(function (error) { console.log(error); }); },
//Delete message export const delMessages = messageId => {return axios.delete(`${local_host}/messages/`+messageId+'/')}
Upload files (work done at the front end)
submitMessage () { //Submit message 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 in es is used. file append in.
//Add message export const addMessage = params => {return axios.post(`${local_host}/messages/`, params, {headers:{ 'Content-Type': 'multipart/form-data' }})}
When addmessage is passed in, the head indicates its type multipart/form-data.
How does drf parse and save files in our database?
parse section of the document.
You can see that drf provides us with a variety of parse s
MultiPartParser
file in the model we can set upload_to
file = models.FileField(upload_to="message/images/", verbose_name="Uploaded Documents", help_text="Uploaded Documents")
Development of Page Interface for User Receiving Address List
The delivery address is also placed in user_operation. Get all the receiving addresses and modify one of them.
Delete a receiving address.
Need lists, additions, updates, deletions: inheritance additions, deletions, modifications, mixin s, but if needed, then there is a viewset that has already helped us.
class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet):
We just need to inherit from the Model ViewSet.
Add a matching Serilizer.
class AddressSerializer(serializers.ModelSerializer): user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M') class Meta: model = UserAddress fields = ("id", "user", "province", "city", "district", "address", "signer_name", "add_time", "signer_mobile")
The user is the current user.
When filling back an address, if it is an address to fill back all its provinces and municipalities, it will be separated, which is more troublesome. So we set three fields for storage. Provincial and Urban Areas
Configuration in viewset
class AddressViewset(viewsets.ModelViewSet): """ Receiving Address Management list: Get the shipping address create: Add Receiving Address update: Update Receiving Address delete: Delete the Receiving Address """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) serializer_class = AddressSerializer def get_queryset(self): return UserAddress.objects.filter(user=self.request.user)
Configure in url:
# Receiving address router.register(r'address', , base_name="address")
Optional job: Validation of additional fields. Such as mobile phone number.
vue and receiving address interface debugging
Interface in vue about receiving address
//Add Receiving Address export const addAddress = params => {return axios.post(`${host}/address/`, params)} //Delete the Receiving Address export const delAddress = addressId => {return axios.delete(`${host}/address/`+addressId+'/')} //Modification of Receiving Address export const updateAddress = (addressId, params) => {return axios.patch(`${host}/address/`+addressId+'/', params)} //Get the shipping address export const getAddress = () => {return axios.get(`${host}/address/`)}
Change all four host s to localhost
src/views/member/receive.vue: This is the component of our receiving address.
When components are created
created () { this.getReceiveInfo(); },
getreceiveInfo() calls the getaddress interface
getReceiveInfo() { //Getting recipient information getAddress().then((response)=> { console.log(response.data); this.receiveInfoArr = response.data; }).catch(function (error) { console.log(error); }); },
ReciveInfoArr traverses the data.
<v-distpicker :province="newInfo.province" :city="newInfo.city" :area="newInfo.district" @province="getProvince" @city="getCity" @area="getArea"></v-distpicker>
Known bug s, set up Chang'an District of Xi'an City, the district does not display.