如何編寫安裝的 Django 應用程序

      網友投稿 852 2025-04-01

      目錄

      先決條件

      在項目中啟動示例 Django 應用程序

      從頭開始創建 Django 項目

      探索收據示例應用程序

      在項目中測試 App

      制作可安裝的 Django 應用

      將您的 Django 應用程序移出項目

      在項目外引導 Django

      使用可安裝的 Django 應用程序運行管理命令

      測試可安裝的 Django 應用

      使用 setup.cfg 定義可安裝包

      使用 tox 測試多個版本

      發布到 PyPI

      結論

      進一步閱讀

      在Django框架中,項目是指特定網站的配置文件和代碼的集合。Django 將業務邏輯分組到它所謂的應用程序中,它們是 Django 框架的模塊。有很多關于如何構建項目和其中的應用程序的文檔,但是當需要打包可安裝的 Django 應用程序時,信息就更難找到了。

      在本教程中,您將學習如何從Django 項目中取出應用程序并將其打包以使其可安裝。打包應用程序后,您可以在PyPI上共享它,以便其他人可以通過pip install

      在本教程中,您將學習:

      編寫獨立應用程序和在項目內部編寫應用程序有什么區別

      如何創建用于發布 Django 應用程序的setup.cfg文件

      如何在Django 項目之外引導 Django,以便您可以測試您的應用程序

      如何使用 Python 和 Django 的多個版本進行測試?tox

      如何使用Twine將可安裝的 Django 應用程序發布到 PyPI

      先決條件

      本教程需要對Django、pip、PyPI、pyenv(或等效的虛擬環境工具)和tox.?要了解有關這些主題的更多信息,請查看:

      Django Tutorials

      What Is Pip? A Guide for New Pythonistas

      How to Publish an Open-Source Python Package to PyPI

      Managing Multiple Python Versions With pyenv

      Getting Started With Testing in Python

      在項目中啟動示例 Django 應用程序

      本教程包含一個工作包,可幫助指導您完成制作可安裝 Django 應用程序的過程。

      即使您最初打算將 Django 應用程序作為包提供,您也可能會從項目內部開始。為了演示從 Django 項目轉移到可安裝的 Django 應用程序的過程,我在 repo 中提供了兩個分支。該項目的分支是一個Django項目的內部應用程序的起始狀態。該主分支是完成安裝的應用程序。

      您還可以在PyPI realpython-django-receipts 包頁面下載完成的應用程序。您可以通過運行安裝該軟件包pip install realpython-django-receipts。

      示例應用程序是收據上行項目的簡短表示。在項目分支中,您將找到一個名為的目錄sample_project,其中包含一個正在運行的 Django 項目。該目錄如下所示:

      sample_project/ │ ├── receipts/ │ ├── fixtures/ │ │ └── receipts.json │ │ │ ├── migrations/ │ │ ├── 0001_initial.py │ │ └── __init__.py │ │ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py │ ├── sample_project/ │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py │ ├── db.sqlite3 ├── manage.py ├── resetdb.sh └── runserver.sh

      在編寫本教程時,Django 的最新版本是 3.0.4,所有測試都是使用 Python 3.7 完成的。本教程中概述的所有步驟都不應與早期版本的 Django 不兼容——我從 Django 1.8 開始使用這些技術。但是,如果您使用的是 Python 2,則需要進行一些更改。為了使示例簡單,我假設整個代碼庫都使用 Python 3.7。

      從頭開始創建 Django 項目

      示例項目和收據應用程序是使用 Djangoadmin命令和一些小的編輯創建的。首先,在干凈的虛擬環境中運行以下代碼:

      $ python -m pip install Django $ django-admin startproject sample_project $ cd sample_project $ ./manage.py startapp receipts

      這將創建sample_project項目目錄結構和receipts應用程序子目錄,其中包含您將用于創建可安裝 Django 應用程序的模板文件。

      接下來,該sample_project/settings.py文件需要進行一些修改:

      添加'127.0.0.1'到ALLOWED_HOSTS設置中,以便您可以在本地進行測試。

      添加'receipts'到INSTALLED_APPS列表中。

      您還需要receipts在sample_project/urls.py文件中注冊應用程序的 URL?。為此,請添加path('receipts/', include('receipts.urls'))到url_patterns列表中。

      探索收據示例應用程序

      該應用程序由兩個 ORM 模型類組成:Item和Receipt.?本Item類包含了描述和成本數據庫字段聲明。成本包含在DecimalField.?使用浮點數來表示貨幣是危險的——在處理貨幣時你應該總是使用定點數。

      該Receipt班是一個收集點Item的對象。這是一個實現ForeignKey在Item該點Receipt。Receipt還包括total()獲取Item包含在 中的對象的總成本Receipt:

      # receipts/models.py from decimal import Decimal from django.db import models class Receipt(models.Model): created = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Receipt(id={self.id})" def total(self) -> Decimal: return sum(item.cost for item in self.item_set.all()) class Item(models.Model): created = models.DateTimeField(auto_now_add=True) description = models.TextField() cost = models.DecimalField(max_digits=7, decimal_places=2) receipt = models.ForeignKey(Receipt, on_delete=models.CASCADE) def __str__(self): return f"Item(id={self.id}, description={self.description}, " \ f"cost={self.cost})"

      如何編寫可安裝的 Django 應用程序

      模型對象為您提供數據庫內容。一個簡短的 Django 視圖返回一個JSON 字典,其中Receipt包含Item數據庫中的所有對象及其對象:

      # receipts/views.py from django.http import JsonResponse from receipts.models import Receipt def receipt_json(request): results = { "receipts":[], } for receipt in Receipt.objects.all(): line = [str(receipt), []] for item in receipt.item_set.all(): line[1].append(str(item)) results["receipts"].append(line) return JsonResponse(results)

      的receipt_json()視圖遍歷所有的Receipt目的,創建一對所述的Receipt對象和所述的列表Item的對象包含在。所有這些都放在字典中并通過 Django 的JsonResponse().

      為了使模型在Django 管理界面中可用,您可以使用一個admin.py文件來注冊模型:

      # receipts/admin.py from django.contrib import admin from receipts.models import Receipt, Item @admin.register(Receipt) class ReceiptAdmin(admin.ModelAdmin): pass @admin.register(Item) class ItemAdmin(admin.ModelAdmin): pass

      此代碼ModelAdmin為每個Receipt和Item類創建一個 Django?,并將它們注冊到 Django 管理員。

      最后,urls.py文件在應用程序中針對 URL 注冊單個視圖:

      # receipts/urls.py from django.urls import path from receipts import views urlpatterns = [ path("receipt_json/", views.receipt_json), ]

      您現在可以包含receipts/urls.py在您的項目url.py文件中,以便在您的網站上提供收據視圖。

      一切就緒后,可以運行./manage.py makemigrations receipts,使用Django admin添加數據,然后訪問/receipts/receipt_json/查看結果:

      $ curl -sS http://127.0.0.1:8000/receipts/receipt_json/ | python3.8 -m json.tool { "receipts": [ [ "Receipt(id=1)", [ "Item(id=1, description=wine, cost=15.25)", "Item(id=2, description=pasta, cost=22.30)" ] ], [ "Receipt(id=2)", [ "Item(id=3, description=beer, cost=8.50)", "Item(id=4, description=pizza, cost=12.80)" ] ] ] }

      在上面的塊中,您使用curl訪問receipt_json視圖,從而產生包含Receipt對象及其對應Item對象的 JSON 響應。

      在項目中測試 App

      Djangounittest用自己的測試功能擴充了 Python包,使您能夠將設備預加載到數據庫中并運行您的測試。收據應用程序定義了一個tests.py文件和一個用于測試的裝置。這個測試絕不是全面的,但它是一個足夠好的概念證明:

      # receipts/tests.py from decimal import Decimal from django.test import TestCase from receipts.models import Receipt class ReceiptTest(TestCase): fixtures = ["receipts.json", ] def test_receipt(self): receipt = Receipt.objects.get(id=1) total = receipt.total() expected = Decimal("37.55") self.assertEqual(expected, total)

      夾具創建兩個Receipt對象和四個對應的Item對象。單擊下面的可折疊部分以仔細查看夾具的代碼。

      receives.json 測試裝置顯示隱藏

      您可以使用 Djangomanage.py命令測試收據應用程序:

      $ ./manage.py test Creating test database for alias 'default'... System check identified no issues (0 silenced). . ---------------------------------------------------------------------- Ran 1 test in 0.013s OK Destroying test database for alias 'default'...

      Runningmanage.py test運行 中定義的單個測試receipts/tests.py并顯示結果。

      制作可安裝的 Django 應用

      您的目標是在沒有項目的情況下共享收據應用程序,并使其可被其他人重復使用。您可以壓縮receipts/目錄并將其分發出去,但這有些限制。相反,您希望將應用程序分成一個包,以便它可以安裝。

      創建可安裝的 Django 應用程序的最大挑戰是 Django 需要一個項目。沒有項目的應用程序只是一個包含代碼的目錄。沒有項目,Django 不知道如何處理您的代碼,包括運行測試。

      將您的 Django 應用程序移出項目

      保留一個示例項目是個好主意,這樣您就可以運行 Django 開發服務器并使用您的應用程序的實時版本。您不會將此示例項目包含在應用程序包中,但它仍然可以存在于您的存儲庫中。按照這個想法,您可以通過將可安裝的 Django 應用程序上移到一個目錄來開始打包它:

      $ mv receipts ..

      目錄結構現在看起來像這樣:

      django-receipts/ │ ├── receipts/ │ ├── fixtures/ │ │ └── receipts.json │ │ │ ├── migrations/ │ │ ├── 0001_initial.py │ │ └── __init__.py │ │ │ ├── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ ├── views.py │ ├── admin.py │ └── apps.py │ ├── sample_project/ │ ├── sample_project/ │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ │ │ ├── db.sqlite3 │ ├── manage.py │ ├── resetdb.sh │ └── runserver.sh │ ├── LICENSE └── README.rst

      要打包您的應用程序,您需要將其從項目中拉出。移動它是第一步。我通常會保留原始項目以進行測試,但我不會將其包含在生成的包中。

      在項目外引導 Django

      現在您的應用程序在 Django 項目之外,您需要告訴 Django 如何找到它。如果您想測試您的應用程序,請運行一個可以找到您的應用程序或運行您的遷移的 Django shell?。您需要配置 Django 并使其可用。

      Django's?settings.configure()anddjango.setup()是在項目之外與您的應用程序交互的關鍵。有關這些調用的更多信息,請參閱 Django 文檔。

      您可能在多個地方需要 Django 的這種配置,因此在函數中定義它是有意義的。創建一個名為的文件,boot_django.py其中包含以下代碼:

      1# boot_django.py 2# 3# This file sets up and configures Django. It's used by scripts that need to 4# execute as if running in a Django server. 5import os 6import django 7from django.conf import settings 8 9BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "receipts")) 10 11def boot_django(): 12 settings.configure( 13 BASE_DIR=BASE_DIR, 14 DEBUG=True, 15 DATABASES={ 16 "default":{ 17 "ENGINE":"django.db.backends.sqlite3", 18 "NAME": os.path.join(BASE_DIR, "db.sqlite3"), 19 } 20 }, 21 INSTALLED_APPS=( 22 "receipts", 23 ), 24 TIME_ZONE="UTC", 25 USE_TZ=True, 26 ) 27 django.setup()

      第 12 和 27 行設置了 Django 環境。該settings.configure()調用采用與settings.py文件中定義的變量等效的參數列表。settings.py使您的應用程序運行所需的任何內容都會傳遞到settings.configure().

      上面的代碼是一個相當精簡的配置。收據應用程序不會對會話或模板執行任何操作,因此INSTALLED_APPS只需要"receipts",并且您可以跳過任何中間件定義。該USE_TZ=True值是必需的,因為Receipt模型包含created時間戳。否則,您將在加載測試夾具時遇到問題。

      使用可安裝的 Django 應用程序運行管理命令

      現在您有了boot_django.py,您可以使用一個非常短的腳本運行任何 Django 管理命令:

      #!/usr/bin/env python # makemigrations.py from django.core.management import call_command from boot_django import boot_django boot_django() call_command("makemigrations", "receipts")

      Django 允許您通過call_command().?您現在可以通過導入和調用boot_django()后跟call_command().

      你的應用程序現在在項目之外,允許你對它做各種各樣的 Django-y 事情。我經常定義四個實用程序腳本:

      load_tests.py?測試您的應用

      makemigrations.py?創建遷移文件

      migrate.py?執行表遷移

      djangoshell.py?生成一個知道你的應用程序的 Django shell

      測試可安裝的 Django 應用

      該load_test.py文件可以像makemigrations.py腳本一樣簡單,但它只能一次運行所有測試。通過添加幾行,您可以將命令行參數傳遞給測試運行器,從而允許您運行選擇性測試:

      1#!/usr/bin/env python 2# load_tests.py 3import sys 4from unittest import TestSuite 5from boot_django import boot_django 6 7boot_django() 8 9default_labels = ["receipts.tests", ] 10 11def get_suite(labels=default_labels): 12 from django.test.runner import DiscoverRunner 13 runner = DiscoverRunner(verbosity=1) 14 failures = runner.run_tests(labels) 15 if failures: 16 sys.exit(failures) 17 18 # In case this is called from setuptools, return a test suite 19 return TestSuite() 20 21if __name__ == "__main__": 22 labels = default_labels 23 if len(sys.argv[1:]) > 0: 24 labels = sys.argv[1:] 25 26 get_suite(labels)

      DjangoDiscoverRunner是一個測試發現類,與 Python 的unittest.?它負責設置測試環境、構建測試套件、設置數據庫、運行測試,然后將其全部拆除。從第 11 行開始,get_suite()獲取測試標簽列表并直接調用DiscoverRunner它們。

      該腳本類似于 Django 管理命令的test作用。該__main__塊將任何命令行參數傳遞給get_suite(),如果沒有,則它將傳遞到應用程序的測試套件中receipts.tests。您現在可以load_tests.py使用測試標簽參數調用并運行單個測試。

      第 19 行是一個特殊情況,可在使用tox.?您將tox在后面的部分中了解更多信息。您還可以DiscoverRunner在下面的可折疊部分中查看潛在的替代品。

      DiscoverRunner 替代方案顯示隱藏

      定義您的可安裝包?setup.cfg

      要將可安裝的 Django 應用程序放在 PyPI 上,您需要先將其放入一個包中。PyPI中期望一個egg,wheel或源分布。這些是使用setuptools.?為此,您需要在與目錄相同的目錄級別創建一個setup.cfg文件和一個setup.py文件receipts。

      但是,在深入研究之前,您需要確保您有一些文檔。您可以在 中包含項目描述setup.cfg,它會自動顯示在 PyPI 項目頁面上。確保寫一個README.rst或類似的關于你的包的信息。

      PyPI默認支持reStructuredText格式,但它也可以處理帶有額外參數的Markdown:

      1# setup.cfg 2[metadata] 3name = realpython-django-receipts 4version = 1.0.3 5description = Sample installable django app 6long_description = file:README.rst 7url = https://github.com/realpython/django-receipts 8license = MIT 9classifiers = 10 Development Status :: 4 - Beta 11 Environment :: Web Environment 12 Intended Audience :: Developers 13 License :: OSI Approved :: MIT License 14 Operating System :: OS Independent 15 Programming Language :: Python :: 3 :: Only 16 Programming Language :: Python :: 3.7 17 Programming Language :: Python :: Implementation :: CPython 18 Topic :: Software Development :: Libraries :: Application Frameworks 19 Topic :: Software Development :: Libraries :: Python Modules 20 21[options] 22include_package_data = true 23python_requires = >=3.6 24setup_requires = 25 setuptools >= 38.3.0 26install_requires = 27 Django>=2.2

      該setup.cfg文件描述了您將構建的包。第 6 行使用file:指令讀取您的README.rst文件。這使您不必在兩個地方編寫長描述。

      第26 行的install_requires條目告訴任何安裝程序,例如,您的應用程序具有的依賴項。您將始終希望將可安裝的 Django 應用程序與其支持的最低 Django 版本聯系起來。pip install

      如果您的代碼具有任何僅運行測試所需的依賴tests_require =項,則您可以添加一個條目。例如,在mock成為標準 Python 庫的一部分之前,tests_require = mock>=2.0.0在setup.cfg.

      pyproject.toml在你的包中包含一個文件被認為是最佳實踐。布雷特·坎農 (Brett Cannon)關于該主題的出色文章可以讓您了解詳細信息。pyproject.toml示例代碼中還包含一個文件。

      您幾乎已準備好為可安裝的 Django 應用程序構建包。測試它的最簡單方法是使用您的示例項目——另一個保留示例項目的好理由。該pip install命令支持本地定義的包。這可用于確保您的應用程序仍然適用于項目。但是,一個警告是setup.cfg在這種情況下它不會單獨工作。您還必須創建一個 shim 版本setup.py:

      #!/usr/bin/env python if __name__ == "__main__": import setuptools setuptools.setup()

      此腳本將自動使用您的setup.cfg文件。您現在可以安裝包的本地可編輯版本以從sample_project.?可以肯定的是,最好從一個全新的虛擬環境開始。requirements.txt在sample_project目錄中添加以下文件:

      # requirements.txt -e ../../django-receipts

      該-e告訴pip,這是一個本地可編輯的安裝。您現在已準備好安裝:

      $ pip install -r requirements.txt Obtaining django-receipts (from -r requirements.txt (line 1)) Collecting Django>=3.0 Using cached Django-3.0.4-py3-none-any.whl (7.5 MB) Collecting asgiref~=3.2 Using cached asgiref-3.2.7-py2.py3-none-any.whl (19 kB) Collecting pytz Using cached pytz-2019.3-py2.py3-none-any.whl (509 kB) Collecting sqlparse>=0.2.2 Using cached sqlparse-0.3.1-py2.py3-none-any.whl (40 kB) Installing collected packages: asgiref, pytz, sqlparse, Django, realpython-django-receipts Running setup.py develop for realpython-django-receipts Successfully installed Django-3.0.4 asgiref-3.2.7 pytz-2019.3 realpython-django-receipts sqlparse-0.3.1

      該install_requires列表setup.cfg告訴pip install它需要Django的。Django 需要asgiref,?pytz, 和sqlparse.?所有依賴項都已處理完畢,您現在應該可以運行sample_projectDjango 開發服務器了。恭喜 - 您的應用程序現在已從示例項目中打包和引用!

      測試多個版本?tox

      Django 和 Python 都在不斷進步。如果您要與全世界共享您的可安裝 Django 應用程序,那么您可能需要在多種環境中進行測試。該tox工具需要一點幫助才能測試您的 Django 應用程序。繼續并在內部進行以下更改setup.cfg:

      1# setup.cfg 2[metadata] 3name = realpython-django-receipts 4version = 1.0.3 5description = Sample installable django app 6long_description = file:README.rst 7url = https://github.com/realpython/django-receipts 8license = MIT 9classifiers = 10 Development Status :: 4 - Beta 11 Environment :: Web Environment 12 Intended Audience :: Developers 13 License :: OSI Approved :: MIT License 14 Operating System :: OS Independent 15 Programming Language :: Python :: 3 :: Only 16 Programming Language :: Python :: 3.7 17 Programming Language :: Python :: Implementation :: CPython 18 Topic :: Software Development :: Libraries :: Application Frameworks 19 Topic :: Software Development :: Libraries :: Python Modules 20 21[options] 22include_package_data = true 23python_requires = >=3.6 24setup_requires = 25 setuptools >= 38.3.0 26install_requires = 27 Django>=2.2 28test_suite = load_tests.get_suite

      第 28 行告訴包管理器使用load_tests.py腳本來獲取它的測試套件。該tox實用程序使用它來運行其測試。記得get_suite()在load_tests.py:

      1# Defined inside load_tests.py 2def get_suite(labels=default_labels): 3 from django.test.runner import DiscoverRunner 4 runner = DiscoverRunner(verbosity=1) 5 failures = runner.run_tests(labels) 6 if failures: 7 sys.exit(failures) 8 9 # If this is called from setuptools, then return a test suite 10 return TestSuite()

      誠然,這里發生的事情有點奇怪。通常,test_suite字段 insetup.cfg指向返回一組測試的方法。當tox調用時setup.py,它讀取test_suite參數并運行load_tests.get_suite()。

      如果這個調用沒有返回一個TestSuite對象,那么tox就會抱怨。奇怪的是,您實際上并不想tox獲得一套測試,因為tox您不知道 Django 測試環境。相反,在第 10 行get_suite()創建 aDiscoverRunner并返回一個空TestSuite對象。

      您不能簡單地DiscoverRunner返回一組測試,因為您必須調用DiscoverRunner.run_tests()Django 測試環境的設置和拆卸才能正確執行。僅僅通過正確的測試是tox行不通的,因為不會創建數據庫。get_suite()運行所有測試,但作為函數調用的副作用而不是作為返回測試套件tox執行的正常情況。

      該tox工具允許您測試多個組合。甲tox.ini文件確定測試環境的哪個組合。下面是一個例子:

      [tox] envlist = py{36,37}-django220, py{36,37}-django300 [testenv] deps = django220: Django>=2.2,<3 django300: Django>=3 commands= python setup.py test

      該文件指出,應針對 Python 3.6 和 3.7 以及 Django 2.2 和 3.0 運行測試。總共有四個測試環境。該commands=部分是您告訴tox通過 調用測試的地方setup.py。這就是您test_suite = load_tests.get_suite在setup.cfg.

      注意:的test子命令setup.py已被棄用。目前,Python 中的打包正在迅速變化。雖然python setup.py test通常不推薦調用,但在這種特定情況下它是有效的。

      發布到 PyPI

      最后,是時候在 PyPI 上分享您的可安裝 Django 應用程序了。有多種工具可用于上傳包,但在本教程中您將重點介紹Twine。以下代碼構建包并調用 Twine:

      $ python -m pip install -U wheel twine setuptools $ python setup.py sdist $ python setup.py bdist_wheel $ twine upload dist/*

      前兩個命令構建包的源代碼和二進制分發版。調用twine上傳到 PyPI。如果您.pypirc的主目錄中有一個文件,那么您可以預設您的用戶名,這樣系統只會提示您輸入密碼:

      [disutils] index-servers = pypi [pypi] username:

      我經常使用一個小的shell腳本來grep從代碼中獲取版本號。然后我調用git tag用版本號標記repo,刪除舊的build/和dist/目錄,并調用上述三個命令。

      有關使用 Twine 的更多詳細信息,請參閱如何將開源 Python 包發布到 PyPI。Twine 的兩個流行替代品是Poetry和Flit。Python 中的包管理正在迅速變化。PEP 517和PEP 518正在重新定義如何描述 Python 包和依賴項。

      結論

      Django 應用程序依賴于 Django 項目結構,因此單獨打包它們需要額外的步驟。您已經了解了如何通過從項目中提取、打包并在 PyPI 上共享來制作可安裝的 Django 應用程序。請務必從以下鏈接下載示例代碼:

      在本教程中,您學習了如何:

      在項目之外使用Django 框架

      在獨立于項目的應用程序上調用 Django管理命令

      編寫一個調用Django 測試的腳本,可選擇使用單個測試標簽

      構建一個setup.py文件來定義你的包

      修改setup.py腳本以適應tox

      使用Twine上傳可安裝的 Django 應用

      您已準備好與全世界分享您的下一個應用程序??鞓肪幋a!

      進一步閱讀

      Django、打包、測試都是非常深奧的話題。那里有很多信息。要深入挖掘,請查看以下資源:

      Django 文檔

      Django 入門:構建投資組合應用程序

      Django 教程

      使用 pyenv 管理多個 Python 版本

      什么是 pip?Python 新手指南

      如何將開源 Python 包發布到 PyPi

      Python 測試入門

      Poetry

      Flit

      PyPI有大量可安裝的 Django 應用程序,值得一試。以下是一些最受歡迎的:

      Django-CSP

      Django reCAPTCHA

      django-allauth

      Haystack

      響應式 Django 管理員

      Django 調試工具欄

      Django Python 數據庫

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel如何在數字間插入逗號(怎么在excel中數字中間有逗號)
      下一篇:在Excel如何將表格加密(如何將Excel表格加密)
      相關文章
      亚洲AV成人影视在线观看| 91亚洲精品视频| 亚洲一区二区三区在线网站| 久久久久亚洲精品无码系列| 中文字幕亚洲乱码熟女一区二区 | 亚洲高清在线视频| 亚洲国产综合无码一区| 亚洲中文字幕无码一区二区三区| 亚洲精品在线视频| 亚洲AV无码一区二三区| www.亚洲色图| 亚洲日韩在线观看| 亚洲色偷偷狠狠综合网| 亚洲一本大道无码av天堂| 久久精品国产精品亚洲人人| 国产av无码专区亚洲国产精品| 亚洲日韩涩涩成人午夜私人影院| 精品国产亚洲一区二区在线观看| 亚洲性日韩精品一区二区三区| 久久久久亚洲?V成人无码| 亚洲综合国产一区二区三区| 在线观看亚洲av每日更新| 亚洲精品美女久久久久99| 亚洲国产精品无码久久久秋霞2| 亚洲激情在线视频| 亚洲精品一卡2卡3卡三卡四卡| 亚洲天堂福利视频| 涩涩色中文综合亚洲| 亚洲国产成人精品无码区二本 | 国产亚洲成av片在线观看| 亚洲Av无码专区国产乱码DVD | 狼人大香伊蕉国产WWW亚洲| 亚洲成A∨人片天堂网无码| 亚洲色欲久久久久综合网| 亚洲午夜久久久久妓女影院| 亚洲AV无码久久精品成人| 亚洲视频在线不卡| 亚洲AV一二三区成人影片| 亚洲精品久久久久无码AV片软件| 亚洲1区2区3区精华液| 亚洲一区二区三区免费|