您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。
一、安裝
$ pip install flask-sqlalchemy
二、配置
配置選項(xiàng)列表 :
SQLALCHEMY_NATIVE_UNICODE | 可以用于顯式禁用原生 unicode 支持。當(dāng)使用 不合適的指定無編碼的數(shù)據(jù)庫默認(rèn)值時(shí),這對(duì)于 一些數(shù)據(jù)庫適配器是必須的(比如 Ubuntu 上某些版本的 PostgreSQL )。|
| SQLALCHEMY_POOL_SIZE | 數(shù)據(jù)庫連接池的大小。默認(rèn)是引擎默認(rèn)值(通常 是 5 ) |
| SQLALCHEMY_POOL_TIMEOUT | 設(shè)定連接池的連接超時(shí)時(shí)間。默認(rèn)是 10 。 |
| SQLALCHEMY_POOL_RECYCLE | 多少秒后自動(dòng)回收連接。這對(duì) MySQL 是必要的, 它默認(rèn)移除閑置多于 8 小時(shí)的連接。注意如果 使用了 MySQL , Flask-SQLALchemy 自動(dòng)設(shè)定這個(gè)值為 2 小時(shí)。|
app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE_URI app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True/False # 每次請(qǐng)求結(jié)束后都會(huì)自動(dòng)提交數(shù)據(jù)庫中的變動(dòng). app.config[""] = app.config[""] = app.config[""] = app.config[""] = DATABASE_URI : mysql : mysql://username:password@hostname/database pgsql : postgresql://username:password@hostname/database sqlite(linux) : sqlite:////absolute/path/to/database sqlite(windows) : sqlite:///c:/absolute/path/to/database
三、初始化示例
from flask import Flask from flask_sqlalchemy import SQLAlchemy base_dir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite:///' + os.path.join(base_dir, 'data.sqlite') app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True db = SQLAlchemy(app)
四、定義模型
模型 表示程序使用的持久化實(shí)體. 在 ORM 中, 模型一般是一個(gè) Python 類, 類中的屬性對(duì)應(yīng)數(shù)據(jù)庫中的表.
Flaks-SQLAlchemy 創(chuàng)建的數(shù)據(jù)庫實(shí)例為模型提供了一個(gè)基類以及一些列輔助類和輔助函數(shù), 可用于定義模型的結(jié)構(gòu).
db.Model # 創(chuàng)建模型, db.Column # 創(chuàng)建模型屬性.
模型屬性類型 :
常用 SQLAlchemy 列選項(xiàng)
示例 :
class Role(db.Model): __tablename__ = "roles" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) def __repr__(self): """非必須, 用于在調(diào)試或測(cè)試時(shí), 返回一個(gè)具有可讀性的字符串表示模型.""" return '<Role %r>' % self.name class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, index=True) def __repr__(self): """非必須, 用于在調(diào)試或測(cè)試時(shí), 返回一個(gè)具有可讀性的字符串表示模型.""" return '<Role %r>' % self.username
五、關(guān)系
關(guān)系型數(shù)據(jù)庫使用關(guān)系把不同表中的行聯(lián)系起來。
常用 SQLAlchemy 關(guān)系選項(xiàng):
(1)一對(duì)多
原理 : 在 “多” 這一側(cè)加入一個(gè)外鍵, 指定 “一” 這一側(cè)聯(lián)結(jié)的記錄.
示例代碼 : 一個(gè)角色可屬于多個(gè)用戶, 而每個(gè)用戶只能有一個(gè)角色.
class Role(db.Model): # ... users = db.relationship('User', backref='role') class User(db.Model): # ... role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) # 外鍵關(guān)系. ############### db.ForeignKey('roles.id') : 外鍵關(guān)系, Role.users = db.relationship('User', backref='role') : 代表 外鍵關(guān)系的 面向?qū)ο笠暯? 對(duì)于一個(gè) Role 類的實(shí)例, 其 users 屬性將返回與角色相關(guān)聯(lián)的用戶組成的列表. db.relationship() 第一個(gè)參數(shù)表示這個(gè)關(guān)系的另一端是哪個(gè)模型. backref 參數(shù), 向 User 模型添加了一個(gè) role 數(shù)據(jù)屬性, 從而定義反向關(guān)系. 這一屬性可替代 role_id 訪問 Role 模型, 此時(shí)獲取的是模型對(duì)象, 而不是外鍵的值.
(2)多對(duì)多
最復(fù)雜的關(guān)系類型,需要用到第三章表,即關(guān)聯(lián)表,這樣多對(duì)多關(guān)系可以分解成原表和關(guān)聯(lián)表之間的兩個(gè)一對(duì)多關(guān)系。
查詢多對(duì)多關(guān)系分兩步 : 遍歷兩個(gè)關(guān)系來獲取查詢結(jié)果。
代碼示例:
registrations = db.Table("registrations", db.Column("student_id", db.Integer, db.ForeignKey("students.id")), db.Column("class_id", db.Integer, db.ForeignKey("classes.id")) ) class Student(db.Model): __tablename__ = "students" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String) classes = db.relationship("Class", secondary=registrations, backref=db.backref("students", lazy="dynamic"), lazy="dynamic") class Class(db.Model): __tablename__ = "classes" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String)
多對(duì)多關(guān)系仍然使用定義一對(duì)多關(guān)系的 db.relationship() 方法進(jìn)行定義, 但在多對(duì)多關(guān)系中, 必須把 secondary 參數(shù)設(shè)為關(guān)聯(lián)表。
多對(duì)多關(guān)系可以在任何一個(gè)類中定義, backref 參數(shù)會(huì)處理好關(guān)系的另一側(cè)。
關(guān)聯(lián)表就是一個(gè)簡(jiǎn)單的表, 不是模型, SQLAlchemy 會(huì)自動(dòng)接管這個(gè)表。
classes 關(guān)系使用列表語義, 這樣處理多對(duì)多關(guān)系比較簡(jiǎn)單。
Class 模型的 students 關(guān)系有 參數(shù) db.backref() 定義. 這個(gè)關(guān)系還指定了 lazy 參數(shù), 所以, 關(guān)系兩側(cè)返回的查詢都可接受額外的過濾器。
自引用關(guān)系
自引用關(guān)系可以理解為多對(duì)多關(guān)系的特殊形式 : 多對(duì)多關(guān)系的兩邊由兩個(gè)實(shí)體變?yōu)橐粋€(gè)實(shí)體。
高級(jí)多對(duì)多關(guān)系
使用多對(duì)多關(guān)系時(shí),往往需要存儲(chǔ)所聯(lián)兩個(gè)實(shí)體之間的額外信息。這種信息只能存儲(chǔ)在關(guān)聯(lián)表中,對(duì)用戶之間的關(guān)注來說,可以存儲(chǔ)用戶關(guān)注另一個(gè)用戶的日期,這樣就能按照時(shí)間順序列出所有關(guān)注者。
為了能在關(guān)系中處理自定義的數(shù)據(jù),必須提升關(guān)聯(lián)表的地位,使其變成程序可訪問的模型。
關(guān)注關(guān)聯(lián)表模型實(shí)現(xiàn):
class Follow(db.Model): __tablename__ = "follows" follower_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True) followed_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True) timestamp = db.Column(db.DateTime, default=datetime.utcnow) # SQLAlchemy 不能直接使用這個(gè)關(guān)聯(lián)表, 因?yàn)槿绻@個(gè)做程序就無法訪問其中的自定義字段. 相反的, 要把這個(gè)多對(duì)多關(guān)系的左右 兩側(cè)拆分成兩個(gè)基本的一對(duì)多關(guān)系, 而且要定義成標(biāo)準(zhǔn)的關(guān)系。
使用兩個(gè)一對(duì)多關(guān)系實(shí)現(xiàn)的多對(duì)多關(guān)系:
class User(UserMixin, db.Model): # ... followd = db.relationship("Follow", foreign_keys=[Follow.follower_id], backref=db.backref("follower", lazy="joined"), lazy="dynamic", cascade="all, delete-orphan") followrs = db.relationship("Follow", foreign_keys=[Follow.followed_id], backref=db.backref("followed", lazy="joined"), lazy="dynamic", cascade="all, delete-orphan") # 這段代碼中, followed 和 follower 關(guān)系都定義為 單獨(dú)的 一對(duì)多關(guān)系. # 注意: 為了消除外鍵歧義, 定義關(guān)系是必須使用可選參數(shù) foreign_keys 指定的外鍵. 而且 db.backref() 參數(shù)并不是指定這兩個(gè) 關(guān)系之間的引用關(guān)系, 而是回引 Follow 模型. 回引中的 lazy="joined" , 該模式可以實(shí)現(xiàn)立即從連接查詢中加載相關(guān)對(duì)象. # 這兩個(gè)關(guān)系中, user 一側(cè)設(shè)定的 lazy 參數(shù)作用不一樣. lazy 參數(shù)都在 "一" 這一側(cè)設(shè)定, 返回的結(jié)果是 "多" 這一側(cè)中的記錄. dynamic 參數(shù), 返回的是查詢對(duì)象. # cascade 參數(shù)配置在父對(duì)象上執(zhí)行的操作相關(guān)對(duì)象的影響. 比如, 層疊對(duì)象可設(shè)定為: 將用戶添加到數(shù)據(jù)庫會(huì)話后, 要自定把所有 關(guān)系的對(duì)象都添加到會(huì)話中. 刪除對(duì)象時(shí), 默認(rèn)的層疊行為是把對(duì)象聯(lián)結(jié)的所有相關(guān)對(duì)象的外鍵設(shè)為空值. 但在關(guān)聯(lián)表中, 刪除記錄 后正確的行為是把執(zhí)行該記錄的實(shí)體也刪除, 因?yàn)檫@樣才能有效銷毀聯(lián)結(jié). 這就是 層疊選項(xiàng)值 delete-orphan 的作用. 設(shè)為 all, delete-orphan 的意思是啟動(dòng)所有默認(rèn)層疊選項(xiàng), 并且還要?jiǎng)h除孤兒記錄。
(3)一對(duì)一
可以看做特殊的 一對(duì)多 關(guān)系. 但調(diào)用 db.relationship() 時(shí) 要把 uselist 設(shè)置 False, 把 多變?yōu)?一。
(4)多對(duì)一
將一對(duì)多關(guān)系,反過來即可,也是一對(duì)多關(guān)系。
六、數(shù)據(jù)庫操作
(1)創(chuàng)建數(shù)據(jù)庫及數(shù)據(jù)表
創(chuàng)建數(shù)據(jù)庫
db.create_all()
示例 :
$ python myflask.py shell > from myflask import db > db.create_all()
如果使用 sqlite , 會(huì)在 SQLALCHEMY_DATABASE_URI 指定的目錄下 多一個(gè)文件,文件名為該配置中的文件名。
如果數(shù)據(jù)庫表已經(jīng)存在于數(shù)據(jù)庫中, 那么 db.create_all() 不會(huì)創(chuàng)建或更新這個(gè)表。
更新數(shù)據(jù)庫
方法一 :
先刪除, 在創(chuàng)建 –> 原有數(shù)據(jù)庫中的數(shù)據(jù), 都會(huì)消失.
> db.drop_all() > db.create_all()
方法二 :
數(shù)據(jù)庫遷移框架 : 可以跟自動(dòng)數(shù)據(jù)庫模式的變化,然后增量式的把變化應(yīng)用到數(shù)據(jù)庫中。
SQLAlchemy 的主力開發(fā)人員編寫了一個(gè) 遷移框架 Alembic, 除了直接使用 Alembic wait, Flask 程序還可使用 Flask-Migrate 擴(kuò)展, 該擴(kuò)展對(duì) Alembic 做了輕量級(jí)包裝, 并集成到 Flask-Script 中, 所有操作都通過 Flaks-Script 命令完成。
① 安裝 Flask-Migrate
$ pip install flask-migrate
② 配置
from flask_migrate import Migrate, MigrateCommand # ... migrate = Migrate(app, db) manager.add_command('db', MigrateCommand)
③ 數(shù)據(jù)庫遷移
a. 使用 init 自命令創(chuàng)建遷移倉(cāng)庫.
$ python myflask.py db init # 該命令會(huì)創(chuàng)建 migrations 文件夾, 所有遷移腳本都存在其中.
b. 創(chuàng)建數(shù)據(jù)路遷移腳本. $ python myflask.py db revision # 手動(dòng)創(chuàng)建 Alemic 遷移 創(chuàng)建的遷移只是一個(gè)骨架, upgrade() 和 downgrade() 函數(shù)都是空的. 開發(fā)者需要使用 Alembic 提供的 Operations 對(duì)象 指令實(shí)現(xiàn)具體操作. $ python myflask.py db migrate -m COMMONT # 自動(dòng)創(chuàng)建遷移. 自動(dòng)創(chuàng)建的遷移會(huì)根據(jù)模型定義和數(shù)據(jù)庫當(dāng)前的狀態(tài)之間的差異生成 upgrade() 和 downgrade() 函數(shù)的內(nèi)容. ** 自動(dòng)創(chuàng)建的遷移不一定總是正確的, 有可能漏掉一些細(xì)節(jié), 自動(dòng)生成遷移腳本后一定要進(jìn)行檢查. c. 更新數(shù)據(jù)庫 $ python myflask.py db upgrade # 將遷移應(yīng)用到數(shù)據(jù)庫中.
(2)插入行
模型的構(gòu)造函數(shù),接收的參數(shù)是使用關(guān)鍵字參數(shù)指定的模型屬性初始值。注意,role 屬性也可使用,雖然他不是真正的數(shù)據(jù)庫列,但卻是一對(duì)多關(guān)系的高級(jí)表示。這些新建對(duì)象的 id 屬性并沒有明確設(shè)定,因?yàn)橹麈I是由 Flask-SQLAlchemy 管理的?,F(xiàn)在這些對(duì)象只存在于 Python 解釋器中,尚未寫入數(shù)據(jù)庫。
>> from myflask import db, User, Role >> db.create_all() >> admin_role = Role(name="Admin") >> mod_role = Role(name="Moderator") >> user_role = Role(name="User") >> user_john = User(username="john", role=admin_role) >> user_susan = User(username="susan", role=mod_role) >> user_david = User(username="david", role=user_role) >> admin_role.name 'Admin' >> admin_role.id None --------- >> db.session.add_all([admin_role, mod_role, user_role, user_john, user_susan, user_david]) # 把對(duì)象添加到會(huì)話中. >> db.session.commit() # 把對(duì)象寫入數(shù)據(jù)庫, 使用 commit() 提交會(huì)話.
(3)修改行
>> admin_role = "Administrator" >> db.session.add(admin_role) >> db.session.commit()
(4)刪除行
>> db.session.delete(mod_role) >> db.session.commit()
(5)查詢行
Flask-SQLAlchemy 為每個(gè)模型類都提供了 query 對(duì)象.
獲取表中的所有記錄
>> Role.query.all() [<Role u'Admin'>, <Role u'Moderator'>, <Role u'User'>] >> User.query.all() [<Role u'john'>, <Role u'susan'>, <Role u'david'>]
查詢過濾器
filter_by() 等過濾器在 query 對(duì)象上調(diào)用, 返回一個(gè)更精確的 query 對(duì)象. 多個(gè)過濾器可以一起調(diào)用, 直到獲取到所需的結(jié)果.
>> User.query.filter_by(role=user_role).all() # 以列表形式,返回所有結(jié)果, >> User.query.filter_by(role=user_role).first() # 返回結(jié)果中的第一個(gè).
filter() 對(duì)查詢結(jié)果過濾,比”filter_by()”方法更強(qiáng)大,參數(shù)是布爾表達(dá)式
# WHERE age<20 users = User.query.filter(User.age<20) # WHERE name LIKE 'J%' AND age<20 users = User.query.filter(User.name.startswith('J'), User.age<20)
查詢過濾器 :
查詢執(zhí)行函數(shù) :
first_or_404() | 返回查詢的第一個(gè)結(jié)果,如果沒有結(jié)果,則終止請(qǐng)求,返回 404 錯(cuò)誤響應(yīng) | |
| get() | 返回指定主鍵對(duì)應(yīng)的行,如果沒有對(duì)應(yīng)的行,則返回 None |
get_or_404() | 返回指定主鍵對(duì)應(yīng)的行,如果沒找到指定的主鍵,則終止請(qǐng)求,返回 404 | |錯(cuò)誤響應(yīng)
| count() | 返回查詢結(jié)果的數(shù)量 |
| paginate() | 返回一個(gè) Paginate 對(duì)象,它包含指定范圍內(nèi)的結(jié)果 |
(6)會(huì)話管理,事務(wù)管理
單個(gè)提交
>> db.session.add(ONE) >> db.session.commit()
多個(gè)提交
>> db.session.add_all([LIST_OF_MEMBER]) >> db.session.commit()
刪除會(huì)話
>> db.session.delete(mod_role) >> db.session.commit()
事務(wù)回滾 : 添加到數(shù)據(jù)庫會(huì)話中的所有對(duì)象都會(huì)還原到他們?cè)跀?shù)據(jù)庫時(shí)的狀態(tài).
>> db.session.rollback()
七、視圖函數(shù)中操作數(shù)據(jù)庫
@app.route('/', methods=['GET', 'POST']) def index(): form = NameForm() if form.validate_on_submit(): user = User.query.filter_by(username=form.name.data).first() if user is None: user = User(username=form.name.data) db.session.add(user) session["known"] = False else: session["known"] = True session["name"] = form.name.data form.name.data = "" # why empty it ? return redirect(url_for("index")) return render_template("index.html", current_time=datetime.utcnow(), form=form, name=session.get("name"), known=session.get("known"))
八、分頁對(duì)象 Pagination
1. paginate() 方法
paginate() 方法的返回值是一個(gè) Pagination 類對(duì)象,該類在 Flask-SQLAlchemy 中定義,用于在模板中生成分頁鏈接。
paginate(頁數(shù)[,per_page=20, error_out=True]) 頁數(shù) : 唯一必須指定的參數(shù), per_page : 指定每頁現(xiàn)實(shí)的記錄數(shù)量, 默認(rèn) 20. error_out : True 如果請(qǐng)求的頁數(shù)超出了返回, 返回 404 錯(cuò)誤; False 頁數(shù)超出范圍時(shí)返回一個(gè),空列表.
示例代碼:
@main.route("/", methods=["GET", "POST"]) def index(): # ... page = request.args.get('page', 1, type=int) # 渲染的頁數(shù), 默認(rèn)第一頁, type=int 保證參數(shù)無法轉(zhuǎn)換成整數(shù)時(shí), 返回默認(rèn)值. pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=current_app.config ["FLASKY_POSTS_PER_PAGE"], error_out=False) posts = pagination.items return render_template('index.html', form=form, posts=posts,pagination=pagination)
2. 分頁對(duì)象的屬性及方法:
Flask_SQLAlchemy 分頁對(duì)象的屬性:
在分頁對(duì)象可調(diào)用的方法:
3. 在模板中與 BootStrap 結(jié)合使用示例
使用 Flaks-SQLAlchemy 的分頁對(duì)象與 Bootstrap 中的分頁 CSS, 可以輕松的構(gòu)造出一個(gè) 分頁導(dǎo)航.
分頁模板宏 _macros.html : 創(chuàng)建一個(gè) Bootstrap 分頁元素, 即一個(gè)有特殊樣式的無序列表.
{% macro pagination_widget(pagination,endpoint) %} <ul class="pagination"> <li {% if not pagination.has_prev %} class="disabled" {% endif %}> <a href="{% if pagination.has_prev %}{{url_for(endpoint, page=paginatin.page - 1, **kwargs)}}{% else %} #{% endif %}"> « </a> </li> {% for p in pagination,.iter_pages() %} {% if p %} {% if p == pagination.page %} <li class="active"> <a href="{{ url_for(endpoint, page=p, **kwargs) }}">{{p}}</a> </li> {% else %} <li> <a href="{{ url_for(endpoint, page = p, **kwargs) }}">{{p}}</a> </li> {% endif %} {% else %} <li class="disabled"><a href="#">…</a> </li> {% endif %} {% endfor %} <li {% if not pagination.has_next %} class="disabled" {% endif%}> <a href="{% if paginatin.has_next %}{{ url_for(endpoint, page=pagination.page+1, **kwargs) }}{% else %} #{% endif %}"> » </a> </li> </ul> {% endmacro %}
導(dǎo)入使用分頁導(dǎo)航
{% extends "base.html" %} {% import "_macros.html" as macros %} ... <div class="pagination"> {{ macro.pagination_widget(pagination, ".index")}} </div>
九、監(jiān)聽事件
1. set 事件
示例代碼 :
from markdown import markdown import bleach class Post(db.Model): # ... body = db.Colume(db.Text) body_html = db.Column(db.Text) # ... @staticmethod def on_changeed_body(target, value, oldvalue, initiator): allowed_tags = ["a", "abbr", "acronym", "b", "blockquote", "code", "em", "i", "li", "ol", "pre", "strong", "ul", "h2", "h3","h4","h5","p"] target.body_html = bleach.linkify(bleach.clean(markdown(value, output_format="html"), tags=allowed_tags, strip=True)) db.event.listen(Post.body, "set", Post.on_changeed_body) # on_changed_body 函數(shù)注冊(cè)在 body 字段上, 是 SQLIAlchemy "set" 事件的監(jiān)聽程序, # 這意味著只要這個(gè)類實(shí)例的 body 字段設(shè)了新值, 函數(shù)就會(huì)自動(dòng)被調(diào)用. # on_changed_body 函數(shù)把 body 字段中的文本渲染成 HTML 格式, # 結(jié)果保存在 body_html 中, 自動(dòng)高效的完成 Markdown 文本到 HTML 的轉(zhuǎn)換
十、記錄慢查詢
十一、Binds 操作多個(gè)數(shù)據(jù)庫
十二、其他
1. ORM 在查詢時(shí)做初始化操作
當(dāng) SQLIAlchemy ORM 從數(shù)據(jù)庫查詢數(shù)據(jù)時(shí), 默認(rèn)不調(diào)用__init__ 方法, 其底層實(shí)現(xiàn)了 Python 類的 __new__() 方法, 直接實(shí)現(xiàn) 對(duì)象實(shí)例化, 而不是通過 __init__ 來實(shí)例化對(duì)象.
如果需要在查詢時(shí), 依舊希望實(shí)現(xiàn)一些初始化操作, 可以使用 orm.reconstructor() 裝飾器或 實(shí)現(xiàn) InstanceEvents.load() 監(jiān)聽事件。
# orm.reconstructor from sqlalchemy import orm class MyMappedClass(object): def __init__(self, data): self.data = data # we need stuff on all instances, but not in the database. self.stuff = [] @orm.reconstructor def init_on_load(self): self.stuff = [] # InstanceEvents.load() from sqlalchemy import event ## standard decorator style @event.listens_for(SomeClass, 'load') def receive_load(target, context): "listen for the 'load' event" # ... (event handling logic) ...
如果只是希望在從數(shù)據(jù)庫查詢生成的對(duì)象中包含某些屬性, 也可以使用 property 實(shí)現(xiàn):
class AwsRegions(db.Model): name=db.Column(db.String(64)) ... @property def zabbix_api(self): return ZabbixObj(zabbix_url) @zabbix_api.setter def zabbix_api(self): raise ValueError("zabbix can not be setted!")
感謝各位的閱讀!關(guān)于Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。