Django实践-10RESTful架构和DRF入门


在这里插入图片描述

Django实践-10RESTful架构和DRF入门

参考

官网:https://www.djangoproject.com/
博客:https://www.liujiangblog.com/
本博客内容参考githttps://gitcode.net/mirrors/jackfrued/Python-100-Days 一些细节问题,大家可以查看git连接。本文主要的改变为把代码升级为django4.1版本。

Django静态文件问题备注:
参考:
Django测试开发-20-settings.py中templates配置,使得APP下的模板以及根目录下的模板均可生效
解决django 多个APP时 static文件的问题
django配置app中的静态文件步骤
Django多APP加载静态文件
django.short包参考:
中间件的应用
Django 前后端分离(REST Framework)
https://www.django-rest-framework.org/

RESTful架构

云计算服务

把软件(Software)、平台(Platform)、基础设施(Infrastructure)做成服务(Service)是很多IT企业都一直在做的事情,这就是大家经常听到的SasS(软件即服务)、PasS(平台即服务)和IasS(基础设置即服务)。
在这里插入图片描述

在这里插入图片描述

SOA服务

  1. SOA包括了关于软件是如何被架构起来的东西,而SaaS是关于软件是如何被应用的。
  2. 在SaaS当中,应用程序可以像任何服务一样被传递,就像你家中电话的语音一样,看起来似乎就是为你的需求量体裁衣得到的。而SOA的定义和这个无丝毫的联系。SOA支持的服务,都是些离散的可以再使用的事务处理,这些事务处理合起来就组成了一个业务流程,是从基本的系统中提取出来的抽象代码。
  3. SOA是一个框架的方法,而SaaS是一种传递模型。
  4. 通过SaaS传递Web服务并不需要SOA。
  5. SaaS主要是指一个软件企业向其它企业提供软件服务。而SOA一般是企业内部搭建系统的基础。SaaS注重的是提供服务的思维。而SOA注重的是实现服务的思维。

实现面向服务的架构(SOA)有诸多的方式,包括RPC(远程过程调用)、Web Service、REST等,在技术层面上,SOA是一种抽象的、松散耦合的粗粒度软件架构;在业务层面上,SOA的核心概念是“重用”和“互操作”,它将系统资源整合成可操作的、标准的服务,使得这些资源能够被重新组合和应用。在实现SOA的诸多方案中,REST被认为是最适合互联网应用的架构,符合REST规范的架构也经常被称作RESTful架构。

REST与RESTful

RESTful的概念

要弄清楚什么是RESTful API,首先要弄清楚什么是REST。REST – REpresentational State Transfer,英语的直译就是“表现层状态转移”。解释一下什么是RESTful:

RESTful:URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。RESTful 是典型的基于HTTP的协议。

Resource:资源,即数据。
Representational:某种表现形式,比如用JSON,XML,JPEG等;
State Transfer:状态变化。通过HTTP动词实现。

RESTful架构是一种基于HTTP协议的Web应用程序设计风格,其特点包括使用HTTP动词(GET、POST、PUT、DELETE等)表示资源操作、使用URI标识资源、通过HTTP状态码表示操作结果等。RESTful架构具有简洁、可扩展、易于理解和实现、与不同编程语言和平台无关等优点,因此在Web服务、移动应用、IoT等领域得到广泛应用。

RESTful API 设计原则和规范
RESTful API 设计原则和规范

资源。资源就是网络上的一个实体,一段文本,一张图片或者一首歌曲。资源总是要通过一种载体来反应它的内容。JSON是现在最常用的资源表现形式。
统一接口。RESTful风格的数据元操CRUD(create,read,update,delete)分别对应HTTP方法:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口。
URI。可以用一个URI(统一资源定位符)指向资源,即每个URI都对应一个特定的资源。要获取这个资源访问它的URI就可以,因此URI就成了每一个资源的地址或识别符。一般的,每个资源至少有一个URI与之对应,最典型的URI就是URL。
无状态。所谓无状态即所有的资源都可以URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而变化。

RESTful API设计准则

应该尽量将API部署在专用域名之下 [https://example.org/api/]
应该将API的版本号放入URL [https://example.org/app/1.0/foo], 但这个是不强制的
路径又被称为终点,表示API的具体地址,每个地址代表一种资源。资源只能是名词不能是动词,而且名词往往和数据库的表名相对应。同时,利用HTTP方法(post, get, put, delete)可以分离网址中资源名称的操作。

RESTful举例

GET:http://www.xxx.com/source/id 获取指定ID的某一类资源。例如GET:http://www.xxx.com/friends/123表示获取ID为123的会员的好友列表。如果不加id就表示获取所有会员的好友列表。
POST:http://www.xxx.com/friends/123表示为指定ID为123的会员新增好友。其他的操作类似就不举例了。

GET /products #返回所有的产品清单
POST /products #将产品新建到集合
GET /products/4 #将获取产品4
PATCH /products/4 #更新产品4(客户端提供改变后的完整资源)
PUT /products/4 #更新产品4(客户端提高改变的额属性)
DELETE /products/4 #删除产品4
HEAD #获取资源的元数据
OPTIONS #获取信息

请求方法(HTTP动词)URI解释
GET/students/获取所有学生
POST/students/新建一个学生
GET/students/ID/获取指定ID的学生信息
PUT/students/ID/更新指定ID的学生信息(提供该学生的全部信息)
PATCH/students/ID/更新指定ID的学生信息(提供该学生的部分信息)
DELETE/students/ID/删除指定ID的学生信息
GET/students/ID/friends/列出指定ID的学生的所有朋友
DELETE/students/ID/friends/ID/删除指定ID的学生的指定ID的朋友

RDF实现

DRF使用入门

参考:https://www.django-rest-framework.org/
在Django项目中,如果要实现REST架构,即将网站的资源发布成REST风格的API接口,可以使用著名的三方库djangorestframework ,我们通常将其简称为DRF。

安装django-rest-framework

安装依赖
pip install djangorestframework==3.14.0
pip install markdown==3.4.3
pip install django-filter==23.1
配置settings.py
  1. 添加INSTALLED_APPS
INSTALLED_APPS = [
    ...
    'rest_framework',
]
  1. 添加urls.py

If you’re intending to use the browsable API you’ll probably also want to add REST framework’s login and logout views. Add the following to your root urls.py file.

urlpatterns = [
    ...
    path('api-auth/', include('rest_framework.urls')),
]

Any global settings for a REST framework API are kept in a single configuration dictionary named REST_FRAMEWORK. Start off by adding the following to your settings.py module:
REST框架API的任何全局设置都保存在一个名为REST_FRAMEWORK的配置字典中。首先在settings.py模块中添加以下内容:

REST_FRAMEWORK = {
	 # 配置默认页面大小
	 'PAGE_SIZE': 10,
	 # 配置默认的分页类
	 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
	 
	 'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S',  # 时间相关的字段
	 
	 # 配置异常处理器
	 # 'EXCEPTION_HANDLER': 'api.exceptions.exception_handler',
	 
	 # 配置默认解析器
	 # 'DEFAULT_PARSER_CLASSES': (
	 # 'rest_framework.parsers.JSONParser',
	 # 'rest_framework.parsers.FormParser',
	 # 'rest_framework.parsers.MultiPartParser',
	 # ),
	 
	 # 配置默认限流类
	 # 'DEFAULT_THROTTLE_CLASSES': (),
	 
	 # 配置默认授权类
	 # 'DEFAULT_PERMISSION_CLASSES': (
	 # 'rest_framework.permissions.IsAuthenticated',
	 # ),
	 
	 # 配置默认认证类
	 # 'DEFAULT_AUTHENTICATION_CLASSES': (
	 # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
	 # ),

    # api调试界面
    'DEFAULT_RENDERER_CLASSES': (
           'rest_framework.renderers.JSONRenderer',   # json渲染
           'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览器渲染(生产环境可关掉)
    ),
}
序列化

首先,我们将定义一些序列化器。让我们创建一个名为polls2/serializer.py的新模块,用于数据表示。
前后端分离的开发需要后端为前端、移动端提供API数据接口,而API接口通常情况下都是返回JSON格式的数据,这就需要对模型对象进行序列化处理。DRF中封装了Serializer类和ModelSerializer类用于实现序列化操作,通过继承Serializer类或ModelSerializer类,我们可以自定义序列化器,用于将对象处理成字典,代码如下所示。

from rest_framework import serializers 
from polls.models import Subject
from django.contrib.auth.models import User, Group

class SubjectSerializer(serializers.ModelSerializer):

    class Meta:
        model = Subject
        fields = '__all__'


class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ['url', 'name']

上面的代码直接继承了ModelSerializer,通过Meta类的model属性指定要序列化的模型以及fields属性指定需要序列化的模型字段,稍后我们就可以在视图函数中使用该类来实现对Subject模型的序列化。

在Group和User中,我们使用的是HyperlinkedModelSerializer的超链接关系。您也可以使用主键和各种其他关系,但是超链接是很好的RESTful设计。

编写视图函数

DRF框架支持两种实现数据接口的方式,一种是FBV(基于函数的视图),另一种是CBV(基于类的视图)。代码如下所示。

注释掉views.py中的原show_subjects函数,添加如下内容

from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from serializer import SubjectSerializer, UserSerializer, GroupSerializer
from django.http import HttpRequest, HttpResponse

from rest_framework.decorators import api_view
from rest_framework.response import Response

# def show_subjects(request):
#     queryset = Subject.objects.all()
#     subjects = []
#     for subject in queryset:
#         # subjects.append({
#         #     'no': subject.no,
#         #     'name': subject.name,
#         #     'intro': subject.intro,
#         #     'isHot': subject.is_hot
#         # })
#         subjects.append(SubjectMapper(subject).as_dict())
#     return JsonResponse(subjects, safe=False,json_dumps_params={'ensure_ascii':False})

@api_view(('GET', ))
def show_subjects(request: HttpRequest) -> HttpResponse:
    subjects = Subject.objects.all().order_by('no')
    # 创建序列化器对象并指定要序列化的模型
    serializer = SubjectSerializer(subjects, many=True)
    # 通过序列化器的data属性获得模型对应的字典并通过创建Response对象返回JSON格式的数据
    return Response(serializer.data)


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]


class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]

对比上一个章节的使用bpmapper实现模型序列化的代码,使用DRF的代码更加简单明了,而且DRF本身自带了一套页面,可以方便我们查看我们使用DRF定制的数据接口,如下图所示。

修改urls.py
from django.urls import include, path
from rest_framework import routers
from polls2 import views as polls2_views

router = routers.DefaultRouter()
router.register(r'users', polls2_views.UserViewSet)
router.register(r'groups', polls2_views.GroupViewSet)


urlpatterns = [
    # ...
    path('api-router/', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
测试
http://127.0.0.1:8000/api/subjects

在这里插入图片描述

http://127.0.0.1:8000/api-auth/login
http://127.0.0.1:8000/api-auth/logout

在这里插入图片描述

admin
admin

http://127.0.0.1:8000/api-router/

在这里插入图片描述

http://127.0.0.1:8000/api-router/users/

在这里插入图片描述

http://127.0.0.1:8000/api-router/groups/

在这里插入图片描述

基于RDF修改原有项目

编写序列化器serializer.py添加如下

from polls.models import Subject, Teacher
class SubjectSimpleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Subject
        fields = ('no', 'name')


class TeacherSerializer(serializers.ModelSerializer):

    class Meta:
        model = Teacher
        exclude = ('subject', )

编写视图函数polls2/views.py中新增show_teachers

from polls.models import Subject, Teacher
from serializer import SubjectSimpleSerializer, TeacherSerializer

@api_view(('GET', ))
def show_teachers(request: HttpRequest) -> HttpResponse:
    try:
        sno = int(request.GET.get('sno'))
        subject = Subject.objects.only('name').get(no=sno)
        teachers = Teacher.objects.filter(subject=subject).defer('subject').order_by('no')
        subject_seri = SubjectSimpleSerializer(subject)
        teacher_seri = TeacherSerializer(teachers, many=True)
        return Response({'subject': subject_seri.data, 'teachers': teacher_seri.data})
    except (TypeError, ValueError, Subject.DoesNotExist):
        return Response(status=404)

配置URL映射。

urlpatterns = [
    # ...
    path('api/teachers/', show_teachers), # 新增
    
]

在static/html目录下新增api_teachers.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>老师信息</title>
    <style>
        #container {
            width: 80%;
            margin: 10px auto;
        }
        .teacher {
            width: 100%;
            margin: 0 auto;
            padding: 10px 0;
            border-bottom: 1px dashed gray;
            overflow: auto;
        }
        .teacher>div {
            float: left;
        }
        .photo {
            height: 140px;
            border-radius: 75px;
            overflow: hidden;
            margin-left: 20px;
        }
        .info {
            width: 75%;
            margin-left: 30px;
        }
        .info div {
            clear: both;
            margin: 5px 10px;
        }
        .info span {
            margin-right: 25px;
        }
        .info a {
            text-decoration: none;
            color: darkcyan;
        }
    </style>
</head>
<body>
    <div id="container">
        <h1>[[ subject.name ]]学科的老师信息</h1>
        <hr>
        <h2 v-if="loaded && teachers.length == 0">暂无该学科老师信息</h2>
        <div class="teacher" v-for="teacher in teachers">
            <div class="photo">
                <img :src="'/static/images/' + teacher.photo" height="140" alt="">
            </div>
            <div class="info">
                <div>
                    <span><strong>姓名:[[ teacher.name ]]</strong></span>
                    <span>性别:[[ teacher.sex | maleOrFemale ]]</span>
                    <span>出生日期:[[ teacher.birth ]]</span>
                </div>
                <div class="intro">[[ teacher.intro ]]</div>
                <div class="comment">
                    <a href="" @click.prevent="vote(teacher, true)">好评</a>&nbsp;&nbsp;
                    (<strong>[[ teacher.good_count ]]</strong>)
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <a href="" @click.prevent="vote(teacher, false)">差评</a>&nbsp;&nbsp;
                    (<strong>[[ teacher.bad_count ]]</strong>)
                </div>
            </div>
        </div>
        <a href="/static/html/api_subjects.html">返回首页</a>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
    <script>
        let app = new Vue({
            el: '#container',
            delimiters: ["[[", "]]"], // ***修改处*** vue 的与django模板语法冲突
            data: {
                subject: {},
                teachers: [],
                loaded: false
            },
            created() {
                fetch('/api/teachers/' + location.search)
                    .then(resp => resp.json())
                    .then(json => {
                        this.subject = json.subject
                        this.teachers = json.teachers
                    })
            },
            filters: {
                maleOrFemale(sex) {
                    return sex? '男': '女'
                }
            },
            methods: {
               vote(teacher, flag) {
                    let url = flag? '/praise/' : '/criticize/'
                    url += '?tno=' + teacher.no
                    fetch(url).then(resp => resp.json()).then(json => {
                        if (json.code === 10000) {
                            if (flag) {
                                teacher.good_count = json.count
                            } else {
                                teacher.bad_count = json.count
                            }
                        }
                    })
                }
            }
        })
    </script>
</body>
</html>

测试

http://127.0.0.1:8000/static/html/api_subjects.html

在这里插入图片描述

http://127.0.0.1:8000/static/html/api_teachers.html?sno=1

在这里插入图片描述

总结

本文主要是Django系列博客。本文是RESTful架构和DRF入门。
步骤如下:

1.安装依赖
2.在settings.py中INSTALLED_APPS注册rest_framework并配置 REST_FRAMEWORK 相关
3.在polls2的添加序列化模块serializer.py
4.在polls2的views.py中添加restful风格的函数
5.在urls.py中配置url映射
6.在static/html中新建前端页面
7.运行测试
如果你看到这里,且博客有帮助,可以关注,点赞,收藏,评论哈💯

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在前面的文章中,我们已经介绍了如何使用DRF编写RESTful API和如何进行身份验证。在本文中,我们将继续探讨如何使用DRF实现前后端分离。具体来说,我们将使用Vue.js作为前端框架,并使用axios实现与后端API的通信。 1. 安装Vue.js和axios 首先,我们需要安装Vue.js和axios。我们可以使用npm来进行安装: ``` npm install vue npm install axios ``` 2. 创建Vue.js应用程序 我们可以使用Vue CLI来创建Vue.js应用程序。在命令行中输入以下命令: ``` npm install -g vue-cli vue init webpack myapp ``` 其中,myapp是应用程序的名称。在创建应用程序时,我们需要回答一些问题,例如选择使用哪种模板、是否安装vue-router等。我们可以根据自己的需要进行选择。 3. 编写Vue.js组件 接下来,我们需要编写Vue.js组件来与后端API进行通信。在本例中,我们将创建一个名为“TaskList”的组件,用于显示任务列表并提供添加任务的功能。 在src/components目录下创建TaskList.vue文件,并编写以下代码: ```html <template> <div> <h2>Tasks</h2> <ul> <li v-for="task in tasks" :key="task.id"> {{ task.title }} </li> </ul> <input type="text" v-model="title"> <button @click="addTask">Add Task</button> </div> </template> <script> import axios from 'axios'; export default { data() { return { tasks: [], title: '' }; }, created() { this.getTasks(); }, methods: { getTasks() { axios.get('http://localhost:8000/api/tasks/') .then(response => { this.tasks = response.data; }); }, addTask() { axios.post('http://localhost:8000/api/tasks/', { title: this.title }) .then(response => { this.tasks.push(response.data); this.title = ''; }); } } }; </script> ``` 在这个组件中,我们首先导入axios库,然后定义了一个名为“TaskList”的组件。在data函数中,我们定义了两个变量:tasks用于存储任务列表,title用于存储新任务的标题。在created函数中,我们调用getTasks函数来获取任务列表。在methods对象中,我们定义了两个方法:getTasks用于获取任务列表,addTask用于添加新任务。在getTasks函数中,我们使用axios库进行HTTP GET请求,并在响应中将tasks变量更新为获取的数据。在addTask函数中,我们使用axios库进行HTTP POST请求,并在响应中将新任务添加到tasks变量中。 4. 引入组件 最后,我们需要将TaskList组件引入Vue.js应用程序。在App.vue文件中,我们可以编写以下代码: ```html <template> <div id="app"> <TaskList /> </div> </template> <script> import TaskList from './components/TaskList.vue'; export default { name: 'App', components: { TaskList } }; </script> ``` 在这个文件中,我们首先导入TaskList组件,然后在components对象中注册它。最后,在模板中调用它。 5. 运行应用程序 现在,我们可以使用以下命令启动Vue.js应用程序: ``` npm run dev ``` 在浏览器中访问http://localhost:8080,您将看到一个任务列表和一个添加任务的表单。当您添加新任务时,它将被添加到列表中并保存到后端API中。 总结 在本文中,我们介绍了如何使用Vue.js和axios实现与DRF后端API的通信,并创建了一个名为“TaskList”的组件来显示任务列表和添加新任务。这是一个简单的示例,但您可以使用类似的方法来创建更复杂的应用程序。 ### 回答2: Django前后端分离实践DRF--09主要是关于Django Rest Framework(DRF)在前后端分离开发中的实践DRF是基于Django的一款强大的Web API框架,它提供了一系列的功能和工具,使得开发者能够轻松地构建和管理API。 在这个实践中,首先我们需要将前端和后端进行分离。前端可以使用任何JavaScript框架,如Vue.js或React来构建用户界面,并通过HTTP请求与后端进行通信。而后端则是使用DjangoDRF来构建API。 DRF提供了一些类和方法,能够帮助我们更方便地开发API。例如,通过使用DRF的序列化器,我们可以轻松地将数据库模型转化为JSON格式。此外,DRF还提供了视图和路由器等组件,使得开发者能够更快速地构建API视图和URL路由。 在实践过程中,我们还可以使用DRF的认证和权限系统来保护API的安全性。DRF支持各种认证方式,如基于Token的认证和基于Session的认证。同时,我们可以基于DRF的权限系统来限制用户对API的访问权限,确保只有经过授权的用户才能进行操作。 此外,DRF还提供了一些其他的功能,如过滤器、分页和搜索等,使得我们能够更精细地控制API的行为和展示方式。 总之,Django前后端分离实践DRF--09主要介绍了如何使用DRF来构建前后端分离的应用。通过DRF提供的强大功能和工具,我们可以更便捷地开发高效、安全的API,并提供给前端进行交互和展示。 ### 回答3: DRFDjango Rest Framework是一种用于构建Web API的强大工具,它使得前后端分离开发成为可能。在实践中,Django的后端提供数据的存储和处理功能,而前端使用DRF来访问API并展示数据。 首先,我们需要在Django中安装和配置DRF。可以通过在settings.py中添加'django_rest_framework'到INSTALLED_APPS列表中来安装DRF。然后,在urls.py中配置API的路由。 在Django中,我们可以使用数据库模型来定义数据模型,在使用DRF时,我们需要创建一个序列化器类来定义返回给前端的数据结构。序列化器由字段组成,可以定义字段的类型、验证规则等。我们可以使用DRF提供的ModelSerializer来快速创建序列化器类,它会自动根据模型的字段来生成对应的序列化器字段。 在视图中,我们可以使用基于类的视图来处理API请求。DRF提供了一系列的视图类,如APIView、ViewSet等,可以根据实际需求选择使用。视图类中的方法对应不同的HTTP操作,如GET、POST、PUT、DELETE等。 DRF还提供了身份验证、权限控制、过滤、排序等功能,可以根据项目的需求进行配置。 使用DRF的前后端分离实践中,前端可以通过发送GET、POST、PUT等请求来获取和操作数据。后端则负责处理请求并返回响应。前端可以通过AJAX、fetch等方法来发送请求并获取数据,然后使用HTML、CSS和JavaScript来展示数据。 在前后端分离开发中,前端和后端可以并行开发,各自独立测试,并且可以轻松地修改API而不会影响到前端界面。这种开发模式使得团队协作更加高效,同时也方便进行项目的维护和扩展。 总而言之,Django前后端分离实践DRF可以极大地提升开发效率和团队协作能力。通过合理配置和使用DRF提供的功能,可以实现强大的API开发,使得前后端分离成为一种高效和可行的开发方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT从业者张某某

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值