diff --git a/README.md b/README.md index fb9b070191c34e4966494f24d90f1556bb0bee60..7dae44c25a80ba0b212c66ce1988afbca9146cb4 100644 --- a/README.md +++ b/README.md @@ -84,3 +84,11 @@ - 设置port为8099 - root_url介绍 +### 2.6 项目download_init配置:[download_init](./download_init/README.md) + +该项目主要实现以下功能: + +- 初始的项目配置目录名修改为config +- 设置ip为`192.168.3.50` +- 设置port为8099 +- download file 介绍 diff --git a/docs/img/DownloadReadme/1.png b/docs/img/DownloadReadme/1.png new file mode 100755 index 0000000000000000000000000000000000000000..c65f2d511991d6b754a129b734fe4b2d38bf1683 Binary files /dev/null and b/docs/img/DownloadReadme/1.png differ diff --git a/download_init/README.md b/download_init/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8203c9baf92c5321aaed2649c7fe7d80a9a250f1 --- /dev/null +++ b/download_init/README.md @@ -0,0 +1,97 @@ +# download_init项目介绍 + +该项目主要实现以下功能: + +- 初始的项目配置目录名修改为config +- 设置ip为`192.168.3.50` +- 设置port为8099 +- download file 介绍 + +## 一、创建项目 +```shell +# 创建项目 +cd ~/django5 +django-admin startproject root_url_init + +# 创建app +~/django5/init +python3 manage.py startapp app + +# 启动项目 +python3 manage.py runserver +``` + +## 二、初始化配置 + +具体修改参见issue:[新建app、配置目录、登录IP和端口号修改](https://gitee.com/rd_management_system/django5/issues/IBEZL4) +- 初始的项目配置目录名修改为config +- 设置ip为`192.168.3.50` +- 设置port为8099 + +## 三、下载功能介绍 + +Django提供三种方式实现文件下载功能,分别是HttpResponse、StreamingHttpResponse和FileResponse, 三者的说明如下: +- HttpResponse是所有响应过程的核心类,它的底层功能类是HttpResponseBase。 +- StreamingHttpResponse是在 HttpResponseBase的基础上进行继承与重写的,它实现流式响应输出(流式响应输出是使用Python的迭代器将数据进行分段处理并传输的)适用于大规模数据响应和文件传输响应。 +- FileResponse是在StreamingHttpResponse 的基础上进行继承与重写的,它实现文件的流式响应输出,只适用于文件传输响应。 + +## 四、三种下载功能实例 + +- views.py代码实现 + +```python +# http download +def http_download(request, *args, **kwargs): + print("Download file is {}".format(DOWNLOAD_FILE)) + with open(DOWNLOAD_FILE, 'rb') as file: + response = HttpResponse(file.read(), content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(DOWNLOAD_FILE) + '"'; + return response + +# stream_download +def file_read(file_path, size=512): + with open(file_path, 'rb') as file: + while True: + file_stream = file.read(size) + if file_stream: + yield file_stream + else: + break + +def stream_download(request, *args, **kwargs): + print("Download file is {}".format(STREAM_DOWNLOAD_FILE)) + response = StreamingHttpResponse(file_read(STREAM_DOWNLOAD_FILE), content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(STREAM_DOWNLOAD_FILE) + '"'; + return response + +# file_download +def file_download(request, *args, **kwargs): + print("Download file is {}".format(FILE_DOWNLOAD_FILE)) + with open(FILE_DOWNLOAD_FILE, 'rb') as file: + response = FileResponse(file_read(FILE_DOWNLOAD_FILE), content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(FILE_DOWNLOAD_FILE) + '"'; + return response +``` + +- download.html代码实现 +```html + + + + + + Itopen Download Test + + +
http download test: Download cat.jpg
+
stream download test: Download avatar.png
+
file download test: Download mouse.jpg
+ + +``` + +- 下载测试 + + 访问静态页面download.html并点击下载:http://192.168.3.50:8099/static/download.html + + ![image-20250104155139318](../docs/img/DownloadReadme/1.png) \ No newline at end of file diff --git a/download_init/app/__init__.py b/download_init/app/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/download_init/app/admin.py b/download_init/app/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/download_init/app/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/download_init/app/apps.py b/download_init/app/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..ed327d22f5ad028ff7fae6c967945e1da8438a82 --- /dev/null +++ b/download_init/app/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AppConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'app' diff --git a/download_init/app/models.py b/download_init/app/models.py new file mode 100644 index 0000000000000000000000000000000000000000..71a836239075aa6e6e4ecb700e9c42c95c022d91 --- /dev/null +++ b/download_init/app/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/download_init/app/tests.py b/download_init/app/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/download_init/app/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/download_init/app/views.py b/download_init/app/views.py new file mode 100644 index 0000000000000000000000000000000000000000..93fea9083a3e46f8220be05169425c19c7a04aa8 --- /dev/null +++ b/download_init/app/views.py @@ -0,0 +1,45 @@ +import os +from django.shortcuts import render, redirect +from django.http import HttpResponse, StreamingHttpResponse, FileResponse + +# Create your views here. + +BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +HTTP_DOWNLOAD_FILE = os.path.join(BASE_DIR, 'download', 'cat.jpg') +STREAM_DOWNLOAD_FILE = os.path.join(BASE_DIR, 'download', 'avatar.png') +FILE_DOWNLOAD_FILE = os.path.join(BASE_DIR, 'download', 'mouse.jpg') + +def index(request, *args, **kwargs): + return HttpResponse("Hello, world!") + +def http_download(request, *args, **kwargs): + print("Download file is {}".format(HTTP_DOWNLOAD_FILE)) + with open(HTTP_DOWNLOAD_FILE, 'rb') as file: + response = HttpResponse(file.read(), content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(HTTP_DOWNLOAD_FILE) + '"'; + return response + +def file_read(file_path, size=512): + """ + 每次获取文件size字节数据 + """ + with open(file_path, 'rb') as file: + while True: + file_stream = file.read(size) + if file_stream: + yield file_stream + else: + break + +def stream_download(request, *args, **kwargs): + print("Download file is {}".format(STREAM_DOWNLOAD_FILE)) + response = StreamingHttpResponse(file_read(STREAM_DOWNLOAD_FILE), content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(STREAM_DOWNLOAD_FILE) + '"'; + return response + +def file_download(request, *args, **kwargs): + print("Download file is {}".format(FILE_DOWNLOAD_FILE)) + with open(FILE_DOWNLOAD_FILE, 'rb') as file: + response = FileResponse(file_read(FILE_DOWNLOAD_FILE), content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(FILE_DOWNLOAD_FILE) + '"'; + return response \ No newline at end of file diff --git a/download_init/config/__init__.py b/download_init/config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/download_init/config/asgi.py b/download_init/config/asgi.py new file mode 100644 index 0000000000000000000000000000000000000000..2d5be099360b2fd1dbc484344401ba6a7e19f9be --- /dev/null +++ b/download_init/config/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for download_init project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + +application = get_asgi_application() diff --git a/download_init/config/settings.py b/download_init/config/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..3f931d2b1b553bcf0e4dc5c66a5d132f50206bca --- /dev/null +++ b/download_init/config/settings.py @@ -0,0 +1,137 @@ +""" +Django settings for download_init project. + +Generated by 'django-admin startproject' using Django 5.1. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +import os +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-z!=moj*x)0770tujkzf1i*99b20h(m(7pm6o6v#qsrz8vn!whq' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [ "*" ] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'app.apps.AppConfig', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'config.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'app', 'templates'), os.path.join(BASE_DIR, 'templates')], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'config.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'mysql_init', + 'USER': 'root', + 'PASSWORD': '123456aA', + 'HOST': '192.168.3.50', + 'PORT': '3306' + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ + +STATIC_URL = 'static/' + +STATICFILES_DIRS = [BASE_DIR / "static", BASE_DIR / "app/static"] + +# 设置媒体路由 +MEDIA_URL = 'media/' + +# 设置media目录的完整路径 +MEDIA_ROOT = BASE_DIR / 'media' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/download_init/config/urls.py b/download_init/config/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..1f2b554e2df129d1c3f588d345e852c1382e2944 --- /dev/null +++ b/download_init/config/urls.py @@ -0,0 +1,28 @@ +""" +URL configuration for download_init project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, re_path +from django.views.generic import RedirectView +import app.views + +urlpatterns = [ + path('admin/', admin.site.urls), + path('index/', app.views.index), + path('http_download/', app.views.http_download, name="http_download"), + path('stream_download/', app.views.stream_download, name="stream_download"), + path('file_download/', app.views.file_download, name="file_download"), +] diff --git a/download_init/config/wsgi.py b/download_init/config/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..557f86489e568964f803dc5f672e08074749ffce --- /dev/null +++ b/download_init/config/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for download_init project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + +application = get_wsgi_application() diff --git a/download_init/download/avatar.png b/download_init/download/avatar.png new file mode 100755 index 0000000000000000000000000000000000000000..c75a45e67805c45d63e485ed572710ad72f85d8e Binary files /dev/null and b/download_init/download/avatar.png differ diff --git a/download_init/download/cat.jpg b/download_init/download/cat.jpg new file mode 100755 index 0000000000000000000000000000000000000000..72f37cde82d2e39a161556b71601040f6629af98 Binary files /dev/null and b/download_init/download/cat.jpg differ diff --git a/download_init/download/mouse.jpg b/download_init/download/mouse.jpg new file mode 100755 index 0000000000000000000000000000000000000000..31fcb4a1362fc69bc34daec636cf16fd69175c09 Binary files /dev/null and b/download_init/download/mouse.jpg differ diff --git a/download_init/manage.py b/download_init/manage.py new file mode 100755 index 0000000000000000000000000000000000000000..37bd3aea7b4bc872a51a8240d4beb1a3125c6d2d --- /dev/null +++ b/download_init/manage.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys +from django.core.management.commands.runserver import Command as Runserver + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + Runserver.default_addr = '192.168.3.50' + Runserver.default_port = '8099' + main() \ No newline at end of file diff --git a/download_init/static/download.html b/download_init/static/download.html new file mode 100644 index 0000000000000000000000000000000000000000..419f0775737e7322dc2bcf0b65908d8eb649dd61 --- /dev/null +++ b/download_init/static/download.html @@ -0,0 +1,13 @@ + + + + + + Itopen Download Test + + +
http download test: Download cat.jpg
+
stream download test: Download avatar.png
+
file download test: Download mouse.jpg
+ + \ No newline at end of file diff --git a/root_url_init/README.md b/root_url_init/README.md index fabc7074f8332570ccb1423ba9a6d1a5088bdc94..57d69cb3b3e30d3341e25d04d2212d18a455aa7d 100644 --- a/root_url_init/README.md +++ b/root_url_init/README.md @@ -11,7 +11,7 @@ ```shell # 创建项目 cd ~/django5 -django-admin startproject static_init +django-admin startproject root_url_init # 创建app ~/django5/init