1. 程式人生 > >關於REST風格API的設計

關於REST風格API的設計

使用者地址管理程式碼

後端

在users/views.py中新增檢視

class AddressViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, GenericViewSet):
    """ 使用者地址新增與修改 """ serializer_class = serializers.UserAddressSerializer permissions = [IsAuthenticated] def get_queryset(self): return self.request.user.addresses.filter(is_deleted=False) # GET /addresses/ def list(self, request, *args, **kwargs): """ 使用者地址列表資料 """ queryset = self.get_queryset() serializer = self.get_serializer(queryset, many=True) user = self.request.user return Response({ 'user_id': user.id, 'default_address_id': user.default_address_id, 'limit': constants.USER_ADDRESS_COUNTS_LIMIT, 'addresses': serializer.data, }) # POST /addresses/ def create(self, request, *args, **kwargs): """ 儲存使用者地址資料 """ # 檢查使用者地址資料數目不能超過上限 count = request.user.addresses.count() if count >= constants.USER_ADDRESS_COUNTS_LIMIT: return Response({'message': '儲存地址資料已達到上限'}, status=status.HTTP_400_BAD_REQUEST) return super().create(request, *args, **kwargs) # delete /addresses/<pk>/ def destroy(self, request, *args, **kwargs): """ 處理刪除 """ address = self.get_object() # 進行邏輯刪除 address.is_deleted = True address.save() return Response(status=status.HTTP_204_NO_CONTENT) # put /addresses/pk/status/  @action(methods=['put'], detail=True) def status(self, request, pk=None): """ 設定預設地址 """ address = self.get_object() request.user.default_address = address request.user.save() return Response({'message': 'OK'}, status=status.HTTP_200_OK) # put /addresses/pk/title/ # 需要請求體引數 title  @action(methods=['put'], detail=True) def title(self, request, pk=None): """ 修改標題 """ address = self.get_object() serializer = serializers.AddressTitleSerializer(instance=address, data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) 

在users/serializers.py中新增序列化器

class UserAddressSerializer(serializers.ModelSerializer):
    """ 使用者地址序列化器 """ province = serializers.StringRelatedField(read_only=True) city = serializers.StringRelatedField(read_only=True) district = serializers.StringRelatedField(read_only=True) province_id = serializers.IntegerField(label='省ID', required=True) city_id = serializers.IntegerField(label='市ID', required=True) district_id = serializers.IntegerField(label='區ID', required=True) class Meta: model = Address exclude = ('user', 'is_deleted', 'create_time', 'update_time') def validate_mobile(self, value): """ 驗證手機號 """ if not re.match(r'^1[3-9]\d{9}$', value): raise serializers.ValidationError('手機號格式錯誤') return value def create(self, validated_data): """ 儲存 """ validated_data['user'] = self.context['request'].user return super().create(validated_data) class AddressTitleSerializer(serializers.ModelSerializer): """ 地址標題 """ class Meta: model = Address fields = ('title',) 

在users/urls.py中新增路由

router = routers.DefaultRouter()
router.register(r'addresses', views.AddressViewSet, base_name='addresses')

urlpatterns += router.urls
# POST /addresses/ 新建  -> create
# PUT /addresses/<pk>/ 修改  -> update
# GET /addresses/ 查詢 -> list # DELETE /addresses/<pk>/ 刪除 -> destroy # PUT /addresses/<pk>/status/ 設定預設 -> status # PUT /addresses/<pk>/title/ 設定標題 -> title 

前端

修改user_center_site.js的mounted

mounted: function(){
        ...
        // 補充獲取地址資料的請求
        axios.get(this.host + '/addresses/', { headers: { 'Authorization': 'JWT ' + this.token }, responseType: 'json' }) .then(response => { this.addresses = response.data.addresses; this.limit = response.data.limit; this.default_address_id = response.data.default_address_id; }) .catch(error => { status = error.response.status; if (status == 401 || status == 403) { location.href = 'login.html?next=/user_center_site.html'; } else { alert(error.response.data.detail); } }) }, 

修改user_center_site.js的methods

        // 儲存地址
        save_address: function(){
            if (this.error_receiver || this.error_place || this.error_mobile || this.error_email || !this.form_address.province_id || !this.form_address.city_id || !this.form_address.district_id ) { alert('資訊填寫有誤!'); } else { this.form_address.title = this.form_address.receiver; if (this.editing_address_index === '') { // 新增地址 axios.post(this.host + '/addresses/', this.form_address, { headers: { 'Authorization': 'JWT ' + this.token }, responseType: 'json' }) .then(response => { // 將新地址新增大陣列頭部 this.addresses.splice(0, 0, response.data); this.is_show_edit = false; }) .catch(error => { console.log(error.response.data); }) } else { // 修改地址 axios.put(this.host + '/addresses/' + this.addresses[this.editing_address_index].id + '/', this.form_address, { headers: { 'Authorization': 'JWT ' + this.token }, responseType: 'json' }) .then(response => { this.addresses[this.editing_address_index] = response.data; this.is_show_edit = false; }) .catch(error => { alert(error.response.data.detail || error.response.data.message); }) } } }, // 刪除地址 del_address: function(index){ axios.delete(this.host + '/addresses/' + this.addresses[index].id + '/', { headers: { 'Authorization': 'JWT ' + this.token }, responseType: 'json' }) .then(response => { // 從陣列中移除地址 this.addresses.splice(index, 1); }) .catch(error => { console.log(error.response.data); }) }, // 設定預設地址 set_default: function(index){ axios.put(this.host + '/addresses/' + this.addresses[index].id + '/status/', {}, { headers: { 'Authorization': 'JWT ' + this.token }, responseType: 'json' }) .then(response => { this.default_address_id = this.addresses[index].id; }) .catch(error => { console.log(error.response.data); }) }, // 展示編輯標題 show_edit_title: function(index){ this.input_title = this.addresses[index].title; for(var i=0; i<index; i++) { this.is_set_title.push(false); } this.is_set_title.push(true); } , // 儲存地址標題 save_title: function(index){ if (!this.input_title) { alert("請填寫標題後再儲存!"); } else { axios.put(this.host + '/addresses/' + this.addresses[index].id + '/title/', { title: this.input_title }, { headers: { 'Authorization': 'JWT ' + token }, responseType: 'json' }) .then(response => { this.addresses[index].title = this.input_title; this.is_set_title = []; }) .catch(error => { console.log(error.response.data); }) } }, // 取消儲存地址 cancel_title: function(index){ this.is_set_title = []; }