热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Flask框架(上)

文章目录Flask框架(上)配置文件默认配置配置项的加载与使用路由系统路由本质CBV写法路由的参数请求与响应请求响应sessionsession源码的执

文章目录


  • Flask 框架 (上)
    • 配置文件
      • 默认配置
      • 配置项的加载与使用

    • 路由系统
      • 路由本质
      • CBV写法
      • 路由的参数

    • 请求与响应
      • 请求
      • 响应

    • session
      • session源码的执行流程

    • 闪现(django 中 message)
      • 请求扩展
      • flask 中间件

    • 蓝图
    • g对象
      • g对象和session的区别




Flask 框架 (上)

配置文件


默认配置

flask支持多种方式进行配置项的新增和修改,默认配置项如下。同 django框架大差不差

{
'DEBUG': get_debug_flag(default=False), 是否开启Debug模式
'TESTING': False, 是否开启测试模式
'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
'SECRET_KEY': None,
'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False,
'LOGGER_NAME': None,
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None,
'APPLICATION_ROOT': None,
'SESSION_COOKIE_NAME': 'session',
'SESSION_COOKIE_DOMAIN': None,
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False,
'EXPLAIN_TEMPLATE_LOADING': False,
'PREFERRED_URL_SCHEME': 'http',
'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True,
'JSONIFY_PRETTYPRINT_REGULAR': True,
'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None,
}

配置项的加载与使用

from flask import Flask,jsonify
app=Flask(__name__)
# 方式一:直接配置--->能够配的参数少
app.secret_key='asdfasdf' # secret_key 用来加密解密的密钥
app.debug=True # 修改了代码,只需要保存,自动热加载
# 方式二:通过app.config字典,配置,这个字典中放了所有的配置
app.config['DEBUG']=False # 都要大写
app.config['MYSQL_HOST'] = '127.0.0.1'
# 方式三:通过settings.py 配置文件--->用得少,django 框架的使用方式
app.config.from_pyfile("settings.py")
# 方式四:通过类来加载对象
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite://:memory:'

app.config.from_object("Config")
# 方式五:通过加载json格式配置文件
app.config.from_json("settings.json")
# 方式六:通过环境变量配置
app.config.from_envvar("环境变量名称")
# 方式七:服务(项目)多了,配置文件多了---》配置中心 nacos 阿波罗
m={}
m=request.get('url') # m的值是dict类型
app.config.from_mapping(m)

路由系统

demo

@app.route('/detail/',methods=['GET'],endpoint='detail')

路由本质

django 中的路由在 urls.py 文件中进行管理 flask 中路由基于装饰器进行管理。实际上,无论是在django 还是 flask 中,只要你愿意,咋样都行

flask 注册路由的两种方式
1. @app.router('/') 推荐使用
def index():
...
2. app.add_url_rule('/', view_func=index)
app.router()--->本质上就是self.add_url_rule,self就是flask对象app

CBV写法

在flask 中,cbv 可以选择继承 View (django 继承的是View) 和 MethodView 两个类

如果继承 View 类,需要重写 dispatch 方法

如果继承 MethodView 类,直接写 get , post 方法即可

class HomeView(MethodView):
methods = ['GET'] # 允许请求方式
decorators = [auth, ] # 加载装饰器


def get(self):
print(request.path)
return 'cbv的homeview'
# 添加路由
# name 是路由别名,跟endpoint一个作用,但是cbv必须传name 也可将路由的加载放在类中
app.add_url_rule('/home',view_func=HomeView.as_view(name='home'))

路由的参数

# app.add_url_rule的参数
1 rule, URL规则, 可以使用转换器 <int:pk>
2 endpoint, 当前路由的别名&#xff0c;如果不传&#xff0c; 默认已函数名作为endpoint&#xff0c;如果函数名重名&#xff0c;就会有两个 重名的地址&#xff0c;报错,主要用来反向解析
源码: endpoint &#61; _endpoint_from_view_func(view_func)
用于反向生成URL&#xff0c;即&#xff1a; url_for(&#39;名称&#39;) # url_for 通过 endpoint 的值反向解析出 url
多个视图函数&#xff0c;如果加同一个装饰器&#xff0c;如果不写endpoint&#xff0c;就会报错
3 view_func, 视图函数名称 如果是cbv 视图类.as_view(name&#61;&#39;xx&#39;)
4 defaults &#61; None, 默认值, 当URL中无参数&#xff0c;函数需要参数时&#xff0c;使用defaults &#61; {&#39;k&#39;: &#39;v&#39;}
为函数提供参数,就是django中的kwargs
5 methods &#61; None, 允许的请求方式&#xff0c;如&#xff1a;["GET", "POST"]
6 strict_slashes &#61; None
对URL最后的 / 符号是否严格要求
7 redirect_to &#61; None, redirect_to&#61;&#39;/home&#39;
#重定向到指定地址
8 子域名访问
subdomain &#61; None,

请求与响应


请求

# http请求中有的东西&#xff0c;都能取出来
print(request.method)
# request.method 提交的方法
# request.args get请求提及的数据
print(request.args)
# request.form post请求提交的数据
print(request.form)
# request.values post和get提交的数据总和
print(request.values)
# request.COOKIEs 客户端所带的COOKIE
print(request.COOKIEs)
# request.headers 请求头
print(request.headers)
# request.path 不带域名&#xff0c;请求路径
print(request.path)
# request.full_path 不带域名&#xff0c;带参数的请求路径
print(request.full_path)
# request.url 带域名带参数的请求路径
print(request.url)
# request.base_url 带域名请求路径
# request.url_root 域名
# request.host_url 域名
# request.host 127.0.0.1:500
print(request.host)
# request.files 接受文件
obj &#61; request.files[&#39;the_file_name&#39;]
obj.save(&#39;/var/www/uploads/&#39; &#43; secure_filename(f.filename))

响应

# 4 件套
return "字符串" # 放回字符串
return render_template(&#39;html模板路径&#39;,**{}) # 返回html文件
return redirect(&#39;/index.html&#39;) # 重定向
return jsonify({&#39;k1&#39;:&#39;v1&#39;}) # json 格式字符串
# 响应头中加东西,四件套都可以使用make_response包裹成响应对象&#xff0c;等同于django中的HTTPResponse
res&#61;make_response(&#39;字符串&#39;)
res.headers[&#39;name&#39;]&#61;&#39;yxh&#39;
return res
# 设置COOKIE
response &#61; make_response(&#39;字符串&#39;)
response.set_COOKIE(&#39;key&#39;, &#39;value&#39;)
return response

session

COOKIE:存放在客户端的键值对
session&#xff1a;存放在客户端的键值对
token:存放在客户端&#xff0c;通过算法来校验

在使用session之前必须现在设置一下密钥

app.secret_key&#61;"asdas" # 值随便写

除请求对象之外&#xff0c;还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 COOKIEs 的基础上实现的&#xff0c;并且对 COOKIEs 进行密钥签名要使用会话&#xff0c;你需要设置一个密钥。 (app.session_interface对象)

设置&#xff1a;session[&#39;username&#39;] &#xff1d; &#39;xxx&#39;
# 在django中发什么三件事&#xff0c;1&#xff0c;生成一个随机的字符串 2 往数据库存 3 写入COOKIE返回浏览器
# 在flask中他没有数据库&#xff0c;但session是怎样实现的&#xff1f;
# 生成一个密钥写入这个COOKIE,然后下次请求的时候&#xff0c;通过这个COOKIE解密&#xff0c;然后赋值给session
# 我们通过app.session_interface来查看
删除&#xff1a;session.pop(&#39;username&#39;, None)

app.session_interface中save_session的参数&#xff08;设置COOKIE的参数&#xff09;

源码:
response.set_COOKIE(
name,
val, # type: ignore
expires&#61;expires,
httponly&#61;httponly,
domain&#61;domain,
path&#61;path,
secure&#61;secure,
samesite&#61;samesite,
)
name,
val ,
expires&#61;None, 超时时间(IE requires expires, so set it if hasn&#39;t been already.)
httponly&#61;False 只能http协议传输&#xff0c;无法被Javascript获取&#xff08;不是绝对&#xff0c;底层抓包可以获取到也可以被覆盖&#xff09;

domain&#61;None, COOKIE生效的域名 你可用这个参数来构造一个跨站COOKIE。如&#xff0c; domain&#61;".example.com"所构造的COOKIE对下面这些站点都是可读的&#xff1a;www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果该参数设置为 None &#xff0c;COOKIE只能由设置它的站点读取
path&#61;&#39;/&#39;, COOKIE生效的路径&#xff0c;/ 表示根路径&#xff0c;特殊的&#xff1a;根路径的COOKIE可以被任何url的页面访问&#xff0c;浏览器只会把COOKIE回传给带有该路径的页面&#xff0c;这样可以避免将COOKIE传给站点中的其他的应用。
secure&#61;False, 浏览器将通过HTTPS来回传COOKIE
samesite&#61;None 将COOKIE的范围限制为仅附加到“相同站点”的请求

session源码的执行流程

处理session&#xff0c;有个一个类SecureCOOKIESessionInterface()&#xff0c;有俩重要方法
-save_seesion
1 把sesion对象&#xff0c;当字典 转成字符串&#xff0c;使用秘钥加密
val &#61; self.get_signing_serializer(app).dumps(dict(session))
2 写入COOKIE返回浏览器 session&#61;加密的字符串
response.set_COOKIE(
app.session_COOKIE_name,
val, # 加密字符串
)
-open_session
1 根据sessionid取出加密字符串
val &#61; request.COOKIEs.get(app.session_COOKIE_name)
2 通过秘钥解密&#xff0c;组装成 session
data &#61; s.loads(val, max_age&#61;max_age)
self.session_class(data)
3 在视图函数中才能正常使用session[&#39;name&#39;]取值&#xff0c;赋值&#xff0c;删除值

可以自定义一个类SecureCOOKIESessionInterface&#xff0c;重写open_session和save_session&#xff0c;把session存到数据库&#xff0c;redis里

闪现&#xff08;django 中 message&#xff09;

-设置: flash(&#39;aaa&#39;)
-取值&#xff1a;get_flashed_message()
-
-假设在a页面操作出错&#xff0c;跳转到b页面&#xff0c;在b页面显示a页面的错误信息
# 本质&#xff1a;
如果在同一次请求中&#xff0c;放到request对象中即可
如果在不同请求中&#xff0c;放到session中&#xff0c;所以使用闪现一定配置秘钥
# 使用
设置&#xff1a;flash(&#39;诱惑美女&#39;)
获取&#xff1a;res&#61;get_flashed_messages()
# 高级使用 按分类设置和获取
设置&#xff1a;
flash(&#39;诱惑美女&#39;,category&#61;&#39;man&#39;)
flash(&#39;诱惑帅哥&#39;,category&#61;&#39;wonmen&#39;)
获取&#xff1a;
res&#61;get_flashed_messages(with_categories&#61;True&#xff0c;category_filter&#61;["man"])

demo

&#64;app.route(&#39;/index&#39;)
def index():
# 从某个地方获取设置过的所有值&#xff0c;并清除。
val &#61; request.args.get(&#39;v&#39;)
if val &#61;&#61; &#39;oldboy&#39;:
return &#39;Hello World!&#39;
flash(&#39;超时错误&#39;,category&#61;"x1")
return "ssdsdsdfsd"
# return redirect(&#39;/error&#39;)
&#64;app.route(&#39;/error&#39;)
def error():
"""
展示错误信息
:return:
如果get_flashed_messages(with_category&#61;True)
"""

data &#61; get_flashed_messages(category_filter&#61;[&#39;x1&#39;])
if data:
msg &#61; data[0]
else:
msg &#61; "..."
return "错误信息&#xff1a;%s" %(msg,)
if __name__ &#61;&#61; &#39;__main__&#39;:
app.run()

请求扩展

和django中间件差不多的玩意&#xff0c;但是可以通过蓝图定义给部分接口使用

1 before_request
类比django中间件中的process_request&#xff0c;在请求收到之前绑定一个函数做一些事情
# 基于它做用户登录认证
&#64;app.before_request
def process_request(*args,**kwargs):
if request.path &#61;&#61; &#39;/login&#39;:
return None
user &#61; session.get(&#39;user_info&#39;)
if user:
return None
return redirect(&#39;/login&#39;)
2 after_request
类比django中间件中的process_response&#xff0c;每一个请求之后绑定一个函数&#xff0c;如果请求没有异常
&#64;app.after_request
def process_response1(response):
print(&#39;process_response1 走了&#39;)
return response
3 before_first_request
第一次请求时,跟浏览器无关
&#64;app.before_first_request
def first():
pass
4 teardown_request
每一个请求之后绑定一个函数&#xff0c;即使遇到了异常
&#64;app.teardown_request
def ter(e):
pass
5 errorhandler
路径不存在时404&#xff0c;服务器内部错误500
&#64;app.errorhandler(404)
def error_404(arg):
return "404错误了"
6 template_global
标签
&#64;app.template_global()
def sb(a1, a2):
return a1 &#43; a2
# {{sb(1,2)}}
7 template_filter
过滤器
&#64;app.template_filter()
def db(a1, a2, a3):
return a1 &#43; a2 &#43; a3
# {{ 1|db(2,3)}}
总结&#xff1a;
1 重点掌握before_request和after_request&#xff0c;
2 注意有多个的情况&#xff0c;执行顺序
3 before_request请求拦截后&#xff08;也就是有return值&#xff09;&#xff0c;response所有都执行

flask 中间件

flask 中间件 和 before_request 和 after_request 实现效果类似。

from flask import Flask
app &#61; Flask(__name__)
&#64;app.route(&#39;/&#39;)
def index():
return &#39;Hello World!&#39;
# 模拟中间件
class Md(object):
def __init__(self,old_wsgi_app):
self.old_wsgi_app &#61; old_wsgi_app
def __call__(self, environ, start_response):
print(&#39;开始之前&#39;)
ret &#61; self.old_wsgi_app(environ, start_response)
print(&#39;结束之后&#39;)
return ret
if __name__ &#61;&#61; &#39;__main__&#39;:
# 1我们发现当执行app.run方法的时候&#xff0c;最终执行run_simple&#xff0c;最后执行app(),也就是在执行app.__call__方法
# 2 在__call__里面&#xff0c;执行的是self.wsgi_app().那我们希望在执行他本身的wsgi之前做点事情。
# 3 所以我们先用Md类中__init__&#xff0c;保存之前的wsgi,然后我们用将app.wsgi转化成Md的对象。
# 4 那执行新的的app.wsgi_app&#xff0c;就是执行Md的__call__方法。
# 把原来的wsgi_app替换为自定义的&#xff0c;

app.wsgi_app &#61; Md(app.wsgi_app)
app.run()

蓝图

视图是一个应用对请求进行响应的函数。 Flask 通过模型把进来的请求 URL 匹配到 对应的处理视图。视图返回数据&#xff0c; Flask 把数据变成出去的响应。 Flask 也可以反 过来&#xff0c;根据视图的名称和参数生成 URL 。

简单点说就是对 不同 app进行路由管理&#xff0c;当前蓝图下的请求扩展只对当前蓝图有效。

# 第一步&#xff1a;定义蓝图对象
user &#61; Blueprint(&#39;user&#39;, __name__)
# 第二步&#xff1a;使用蓝图写路径&#xff0c;写请求扩展(只针对于当前蓝图生效)
&#64;user.route(&#39;/index&#39;)
# 第三步&#xff1a;把蓝图注册进app中
app.register_blueprint(user)

使用蓝图结构案例

目录结构&#xff1a;

-flask_pro
-flask_test
-__init__.py
-static
-templates
-views
-order.py
-user.py
-manage.py

_init.py

from flask import Flask
app&#61;Flask(__name__)
from flask_test.views import user
from flask_test.views import order
app.register_blueprint(user.us)
app.register_blueprint(order.ord)

manage.py

from flask_test import app
if __name__ &#61;&#61; &#39;__main__&#39;:
app.run(port&#61;8008)

user.py

from flask import Blueprint
us&#61;Blueprint(&#39;user&#39;,__name__)
&#64;us.route(&#39;/login&#39;)
def login():
return &#39;login&#39;

order.py

from flask import Blueprint
ord&#61;Blueprint(&#39;order&#39;,__name__)
&#64;ord.route(&#39;/test&#39;)
def test():
return &#39;order test&#39;

总结&#xff1a;

1 xxx &#61; Blueprint(&#39;account&#39;, name,url_prefix&#61;&#39;/xxx&#39;) &#xff1a;蓝图URL前缀&#xff0c;表示url的前缀&#xff0c;在该蓝图下所有url都加前缀
2 xxx &#61; Blueprint(&#39;account&#39;, name,url_prefix&#61;&#39;/xxx&#39;,template_folder&#61;&#39;tpls&#39;)&#xff1a;给当前蓝图单独使用templates&#xff0c;向上查找&#xff0c;当前找不到&#xff0c;会找总templates
3 蓝图的befort_request&#xff0c;对当前蓝图有效
4 大型项目&#xff0c;可以模拟出类似于django中app的概念

g对象

g对象 是global的缩写&#xff0c;类似于 django 框架中的 request.context 属性。目的都是为了在不污染 request 对象前提下&#xff0c;实现在同一个请求中&#xff0c;传递数据,上下文传递&#xff0c;赋值取值只针对于当次请求生效。

from flask import g
# 设置值
g.name &#61; "yxh"
# 取值
name &#61; g.name
name &#61; g.get("name")
--------
from flask import Flask, g
app &#61; Flask(__name__)
def test_g():
print(g.get(&#39;name&#39;, None))
g.name &#61; &#39;李四&#39;
&#64;app.route(&#39;/test&#39;)
def test():
g.name &#61; &#39;张三&#39;
test_g() # 控制台会打印&#39;张三&#39;
print(g.name) # 李四
return &#39;test&#39;
if __name__ &#61;&#61; &#39;__main__&#39;:
app.run()

g对象和session的区别

session对象是可以跨request的&#xff0c;只要session还未失效&#xff0c;不同的request的请求会获取到同一个session&#xff0c;但是g对象不是&#xff0c;g对象不需要管过期时间&#xff0c;请求一次就g对象就改变了一次&#xff0c;或者重新赋值了一次






推荐阅读
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • adfs是什么_培训与开发的概念
    adfs是什么_培训与开发的概念(如您转载本文,必须标明本文作者及出处。如有任何疑问请与我联系me@nap7.com)ADFS相关开发技术的中文资料相对匮乏,之前在弄这个东西的时候 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 【爬虫】关于企业信用信息公示系统加速乐最新反爬虫机制
    ( ̄▽ ̄)~又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。升级后网站的层次结构并没有太多变化,表面上 ... [详细]
author-avatar
橄榄村
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有