# cash **Repository Path**: slcnx/cash ## Basic Information - **Project Name**: cash - **Description**: 一个demo应用 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-12-07 - **Last Updated**: 2024-11-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README --- title: 利用django快速生成网页 tags: - django categories: - [devops,python,web,django] date: 2022-12-07 09:40:24 --- # 对数据进行展示 需求:实现此网页一样的内容,网页:http://www.shareswizard.com/kzz_quotations,数据在源码库中。 源码库: # 环境依赖 ## docker desktop windows上需要运行docker容器,就需要安装这个 https://docs.docker.com/desktop/install/windows-install/#install-interactively ## navicat 此应用是付费软件,功能特别好。支持mysql, sqlite, oracle, pgsql, mariadb, mongodb, sqlserver等数据库的连接,纯交互式操作mysql的CURD, 备份恢复,等操作。 https://learnku.com/articles/67706 ## mysql 基于docker运行mysql, 非常方便。 为了加速获取docker image, 需要配置镜像,https://yeasy.gitbook.io/docker_practice/install/mirror#windows-10 ```powershell G:/docker-volumes/mysql/my.cnf [mysqld] character-set-client-handshake = FALSE character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect = 'SET NAMES utf8mb4' innodb_large_prefix = ON innodb-file-per-table = ON innodb_file_format = BARRACUDA innodb_default_row_format = dynamic [client] default-character-set=utf8mb4 docker pull mariadb:10.3.37-focal docker run --restart always -d -p 3306:3306 --name mysql -v G:/docker-volumes/mysql/my.cnf:/etc/mysql/conf.d/my.cnf -v G:/docker-volumes/mysql/data:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD="1" mariadb:10.3.37-focal ``` navicat中导入init.sql ## anaconda 另一个python(官方python, python.org)发行版,是windows 用户的最佳选择。 内建大量预编译的python模块,我们不需要担心windows上模块安装不成功的问题。 https://docs.anaconda.com/anaconda/install/windows/ - [Download the Anaconda installer](https://www.anaconda.com/). - Go to your Downloads folder and double-click the installer to launch. - Windows: Click **Start**, search for Anaconda Navigator, and click to open. - 普通用户运行 anaconda prompt - Enter `conda list`. If Anaconda is installed and working, this will display a list of installed packages and their versions. - 使用anaconda 添加python虚拟环境 https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#managing-python ```powershell # 查看版本 conda search python # 添加虚拟环境 conda create -n py310 python=3.10 # 激活环境 # # To activate this environment, use # # $ conda activate py310 # # To deactivate an active environment, use # # $ conda deactivate Retrieving notices: ...working... done # 查看conda环境 conda info --envs # pip 环境 (py310) C:\Users\slc>conda list # packages in environment at F:\anaconda3\envs\py310: # # Name Version Build Channel bzip2 1.0.8 he774522_0 ca-certificates 2022.10.11 haa95532_0 certifi 2022.9.24 py310haa95532_0 libffi 3.4.2 hd77b12b_6 openssl 1.1.1s h2bbff1b_0 pip 22.2.2 py310haa95532_0 python 3.10.8 h966fe2a_1 setuptools 65.5.0 py310haa95532_0 sqlite 3.40.0 h2bbff1b_0 tk 8.6.12 h2bbff1b_0 tzdata 2022g h04d1e81_0 vc 14.2 h21ff451_1 vs2015_runtime 14.27.29016 h5e58377_2 wheel 0.37.1 pyhd3eb1b0_0 wincertstore 0.2 py310haa95532_2 xz 5.2.8 h8cc25b3_0 zlib 1.2.13 h8cc25b3_0 ``` - 使用anaconda navigator添加python虚拟环境 https://docs.anaconda.com/navigator/getting-started/#managing-environments ## pycharm 在windows上写python代码,建议使用pycharm, 支持语法高亮,补全,查源码,断点调试,快速生成方法,生成python包,复制代码引用路径,等等实用的功能。 https://www.guru99.com/how-to-install-python.html#:~:text=Step%201)%20To%20download%20PyCharm,setup%20wizard%20should%20have%20started. - 添加存在的python到Pycharm项目 https://docs.anaconda.com/anaconda/user-guide/tasks/pycharm/#configuring-a-pycharm-project-with-an-existing-conda-environment ## django python语言的web框架,django, flask, aiohttp, 等等,django内建大量的模块,虽然重一点,但是使用起来非常方便。要求我们掌握django很多知识。 参考: http://blog.mykernel.cn/DevOps/18-django%E9%A1%B9%E7%9B%AE%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA.html ```powershell # 安装必要的包 pip install django mysqlclient djangorestframework django-filter djangorestframework-simplejwt drf_spectacular ``` - `django` web框架 - `mysqlclient` python连接mysql的驱动 - `djangorestframework` 基于django框架的restful框架, 后端api专用 - `django-filter` django rest使用的搜索和过滤功能 - `djangorestframework-simplejwt` django rest使用的jwt认证功能 - `drf_spectacular` django restful框架生成swagger文档 # 配置django ## 生成crash项目 ```powershell django-admin.exe startproject crash . ``` ## 配置项目 crash/settings.py ```python # 最后1行添加 INSTALLED_APPS += [ # ... 'rest_framework', 'rest_framework_simplejwt', 'django_filters', 'drf_spectacular', ] ## 数据库配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'crash', # 库名 'USER': 'root', # mysql user 'PASSWORD': '', # mysql pass 'HOST': '127.0.0.1', # mysql host 'PORT': '3306', # mysql port } } ## 日志配置 import os LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'root': { 'handlers': ['console'], 'level': 'WARNING', }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': False, }, }, } ## 本地化 LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' # 模板静态文件 STATIC_URL = '/static/' STATICFILES_DIRS = [BASE_DIR / 'static'] # django rest 配置 REST_FRAMEWORK = { # openapi 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', # 全局权限处理 'DEFAULT_PERMISSION_CLASSES': [ # # 不配置时AllowAny,不认证或未认证(有无token)都可以进入视图。 # 'rest_framework.permissions.IsAuthenticated', # 配置后,带了token才允许 # 'utils.permissions.IsSuperUser', # 配置后,带了token才允许 # 'utils.permissions.DMPORM' ], # 搜索功能 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend', 'rest_framework.filters.SearchFilter'], # 分页 # 'DEFAULT_PAGINATION_CLASS': 'utils.paginations.PageNumberPagination', # 'PAGE_SIZE': 100, # 全局异常处理 # 'EXCEPTION_HANDLER': 'utils.exceptions.global_exception_handler', # token认证 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ) } # 文档配置 SPECTACULAR_SETTINGS = { 'TITLE': 'crash的API', 'DESCRIPTION': '睿哥的文档', 'VERSION': '1.9.0', 'SERVE_INCLUDE_SCHEMA': False, "SWAGGER_UI_SETTINGS": { "deepLinking": True, "persistAuthorization": True, "displayOperationId": True, }, } # JWT认证配置 from datetime import timedelta SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30), 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), } ``` ## 配置crash/urls.py,准备swagger和jwt相关的url ```python from django.contrib import admin from django.urls import path, include from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, SpectacularRedocView urlpatterns = [ path('admin/', admin.site.urls), # 。。。。 path('doc/schema/', SpectacularAPIView.as_view(), name='schema'), path('doc/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), path('doc/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc') ] ``` ## 项目目录下准备static目录,并进行生成django相关的数据表 ```bash python .\manage.py migrate ``` 此操作会在crash/settings.py定义的数据库中, 添加几个表 - `auth_group` - `auth_permission` - `auth_user` - `auth_user_gruops` - `django_admin_log` - `django_content_type` - `django_migrations` 迁移表结构的位置 ## 生成demoapp应用 生成应用 ``` python manage.py startapp demoapp ``` 此操作会在django项目目录下,生成demoapp目录,目录中有几个文件 ```powershell 13:11 [PS] D:\Documents\Downloads\crash :> ls -name .\demoapp\ models.py # 应用数据保存位置 migrations # 数据保存结构变化的迁移文件生成的目录 admin.py # 对保存的数据,管理的目录 apps.py # 当前demoapp应用的入口文件 tests.py # 当前应用的测试文件 views.py # 用户请求当前应用的处理函数位置 __init__.py # 当前dmeoapp目录是一个包 ``` 添加demoapp/urls.py ```python from django.urls import path from .views import DemoViewSet from rest_framework.routers import SimpleRouter router = SimpleRouter() # 利用router注册多个,建议prefix一定写, 如果''就出问题 router.register('', DemoViewSet) # CRUD /demoapp/mgr/ list create and /demoapp/mgr/ retrive update destory urlpatterns = [ ] + router.urls ``` 添加demoapp/views.py ```python from django_filters.rest_framework import DjangoFilterBackend from drf_spectacular.utils import extend_schema from rest_framework.request import Request from rest_framework.viewsets import ModelViewSet from rest_framework.filters import SearchFilter ### model from django.db import models class DemoTable(models.Model): name = models.CharField(max_length=300) description = models.CharField(max_length=300) ### searilizer from rest_framework.serializers import ModelSerializer class DemoSerializer(ModelSerializer): class Meta: model = DemoTable fields = '__all__' @extend_schema(tags=['users']) class DemoViewSet(ModelViewSet): queryset = DemoTable.objects.all() serializer_class = DemoSerializer # permission_classes = [] # 移除全局权限 # pagination_class = None # None不分页; PageNumberPagination 自定分页 # 列表 get post --> list/create # 详情 get put patch delete --> retrieve/update/partial-update/destroy # 精确匹配 # filter_backends = [DjangoFilterBackend] # 默认全局 filterset_fields = ['name', 'description'] # 查询字段名和查询参数名 ?name=xxxx 字段名也得name, = # 模糊匹配 # filter_backends = [SearchFilter] # 默认全局 search_fields = ['name', 'description'] @extend_schema('create', request=DemoSerializer) def create(self, request:Request, *args, **kwargs): return super().create(request, *args, **kwargs) ``` > 通常,会将`DemoTable` `DemoSerializer`这2个类单独放在demoapp应用目录下的 models.py中,searilizers.py文件中。这里方便起测试示例。我就直接启动了。 crash/urls.py添加映射 ```python from django.urls import path, include urlpatterns = [ # ... path('demoapps/',include('demoapp.urls')), # 。。。。 ] ``` 由于我们需要使用django.db.models管理功能,需要需要注册应用 crash/settings.py ```python INSTALLED_APPS += [ # ... 'demoapp', ] ``` 生成迁移文件 ```powershell (py310) D:\Documents\Downloads\crash>python manage.py makemigrations demoapp (0.000) SELECT VERSION(), @@sql_mode, @@default_storage_engine, @@sql_auto_is_null, @@lower_case_table_names, CONVERT_TZ('2001-01-01 01:00:00', 'UTC', 'UTC') IS NOT NULL ; args=None; alias=default (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None; alias=default (0.000) SHOW FULL TABLES; args=None; alias=default (0.000) SELECT `django_migrations`.`id`, `django_migrations`.`app`, `django_migrations`.`name`, `django_migrations`.`applied` FROM `django_migrations`; args=(); alias=default Migrations for 'demoapp': demoapp\migrations\0001_initial.py - Create model DemoTable (py310) D:\Documents\Downloads\crash>python manage.py migrate ``` 启动应用 ```powershell (py310) D:\Documents\Downloads\crash>python manage.py runserver Watching for file changes with StatReloader Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). (0.000) SELECT VERSION(), @@sql_mode, @@default_storage_engine, @@sql_auto_is_null, @@lower_case_table_names, CONVERT_TZ('2001-01-01 01:00:00', 'UTC', 'UTC') IS NOT NULL ; args=None; alias=default (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None; alias=default (0.000) SHOW FULL TABLES; args=None; alias=default (0.000) SELECT `django_migrations`.`id`, `django_migrations`.`app`, `django_migrations`.`name`, `django_migrations`.`applied` FROM `django_migrations`; args=(); alias=default December 07, 2022 - 13:25:49 Django version 4.1.4, using settings 'crash.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK. ``` 现在获取swagger地址,http://127.0.0.1:8000/doc/schema/swagger-ui/ ![image-20221207132937382](http://myapp.img.mykernel.cn/2022/12/07/20221207132938.png) django restframwork自带的测试接口 ![image-20221207133009369](http://myapp.img.mykernel.cn/2022/12/07/20221207133010.png) - 此处有2条数据,直接在这个页面下方填写name, description,即可完成添加数据。 # 完成demoappv1应用 这里名称是demoappv1,其实我准备将需求中的数据通过demoappv1应用管理 ```python python manage.py startapp demoappv1 # 配置 crash/settings.py INSTALLED_APPS += [ # ... 'demoappv1', ] # 主路由crash/urls.py path('demoappv1s/',include('demoappv1.urls')), # demoappv1的路由 demoappv1/urls.py from django.urls import path from .views import DemoViewSet from rest_framework.routers import SimpleRouter router = SimpleRouter() urlpatterns = [ ] + router.urls # demoappv1的视图 demoappv1/views.py from django_filters.rest_framework import DjangoFilterBackend from drf_spectacular.utils import extend_schema from rest_framework.request import Request from rest_framework.viewsets import ModelViewSet from rest_framework.filters import SearchFilter from django.db import models class DemoTable(models.Model): name = models.CharField(max_length=300) description = models.CharField(max_length=300) from rest_framework.serializers import ModelSerializer class DemoSerializer(ModelSerializer): class Meta: model = DemoTable fields = '__all__' @extend_schema(tags=['users']) class DemoViewSet(ModelViewSet): queryset = DemoTable.objects.all() serializer_class = DemoSerializer search_fields = ['name', 'description'] @extend_schema('create', request=DemoSerializer) def create(self, request:Request, *args, **kwargs): return super().create(request, *args, **kwargs) ``` 现在只需要添加model, 由于已经在源码库中有现成的表了,我们只需要导入表之后,基于此表生成model, ```powershell (py310) D:\Documents\Downloads\crash>python manage.py inspectdb my_cashs_backT class MyCashsBackt(models.Model): code_id = models.AutoField(primary_key=True) account = models.CharField(max_length=255, blank=True, null=True) total_account_amount = models.FloatField(blank=True, null=True) code = models.CharField(max_length=255, blank=True, null=True) code_name = models.CharField(max_length=255, blank=True, null=True) buy_date = models.DateField(blank=True, null=True) first_day_rate = models.CharField(max_length=255, blank=True, null=True) first_day_rate_flag = models.IntegerField() my_price = models.FloatField(blank=True, null=True) num = models.IntegerField(blank=True, null=True) hold_money = models.IntegerField(blank=True, null=True) close_price = models.CharField(max_length=255, blank=True, null=True) my_rate = models.FloatField(blank=True, null=True) my_cash = models.IntegerField(blank=True, null=True) max_price = models.CharField(max_length=255, blank=True, null=True) max_rate = models.FloatField(blank=True, null=True) min_price = models.CharField(max_length=255, blank=True, null=True) min_rate = models.FloatField(blank=True, null=True) die_max_rate = models.CharField(max_length=20, blank=True, null=True) die_max_price = models.CharField(max_length=255, blank=True, null=True) die_min_rate = models.CharField(max_length=20, blank=True, null=True) die_min_price = models.CharField(max_length=255, blank=True, null=True) flag = models.IntegerField() level = models.CharField(max_length=255, blank=True, null=True) is_die = models.IntegerField() die_date = models.DateField(blank=True, null=True) interval_date = models.IntegerField(blank=True, null=True) update_date = models.DateTimeField(blank=True, null=True) class Meta: managed = False db_table = 'my_cashs_backT' ``` 将生成的model,追加到demoappv1/models.py文件中,修改类名为DemoTable,同时删除views.py中的model DemoTable,快速引入这个DemoTable。 再次运行 ``` (py310) D:\Documents\Downloads\crash>python manage.py runserver ``` ![image-20221207134712718](http://myapp.img.mykernel.cn/2022/12/07/20221207134714.png) ## 使用django-admin自带后台展示 通过django admin完成,demoappv1/admin.py ```python from django.contrib import admin from .models import DemoTable class DemoTableAdmin(admin.ModelAdmin): list_display = [ "account", "code", "code_name", "buy_date", "my_price", "num", "hold_money", "close_price", "my_rate", "my_cash", "max_price", "max_rate", "min_price", "min_rate", "die_max_rate", "die_max_price", "die_min_rate", "die_min_price", "flag", "is_die", "die_date", "interval_date" ] admin.site.register(DemoTable, DemoTableAdmin) ``` 生成用户 ``` (py310) D:\Documents\Downloads\crash>python manage.py createsuperuser ``` 访问后台地址http://localhost:8000/admin,用户admin,密码admin。 ![image-20221207135822530](http://myapp.img.mykernel.cn/2022/12/07/20221207135823.png) ## 使用前端展示 不会, ... # 部署应用 先记录python版本和依赖的包 ``` pip freeze > requirements.txt # 同版本,可以切换补丁版本。3.8.x python -V > python-version.txt ``` 准备python打包的配置 项目根目录下setup.cfg ```ini [metadata] name = cash version = "1.1.0" description = cash license = BSD 3-Clause License classifiers = Framecash :: Django Programming Language :: Python :: 3 requires_python = >=3.10 author = liangcheng url = https://blog.mykernel.cn [options] zip_safe = False # MANIFEST.in https://packaging.python.org/en/latest/guides/using-manifest-in/#manifest-in-commands include_package_data = True packages = find: # auto isntall from pypy install_requires = # pip freeze asgiref==3.5.2 attrs==22.1.0 cffi==1.15.1 cryptography==38.0.4 Django==4.1.4 django-filter==22.1 djangorestframework==3.14.0 djangorestframework-simplejwt==5.2.2 drf-spectacular==0.24.2 inflection==0.5.1 Jinja2==3.1.2 jsonschema==4.17.3 MarkupSafe==2.1.1 mysqlclient==2.1.1 packaging==21.3 pycparser==2.21 PyJWT==2.6.0 pyparsing==3.0.9 pyrsistent==0.19.2 pytz==2022.6 PyYAML==6.0 resolvelib==0.8.1 sqlparse==0.4.3 tzdata==2022.7 uritemplate==4.1.1 wincertstore==0.2 # python python_requires = >=3.10 # ['employee', 'hello_backend', 'user', 'utils', 'employee.migrations', 'user.migrations'] [options.packages.find] where = . # [options.entry_points] # console_scripts = # cli-name = hello_backend.wsgi:application ``` 准备 项目根目录下setup.py ``` from setuptools import setup import sys print(sys.getfilesystemencoding()) setup() ``` 准备 项目根目录下MANIFEST.in ```python # include file1 file2 ... #include user/a.txt include python-version.txt include requirements.txt include use.ini include manage.py include LICENSE include README.rst #recursive-include app/static * #recursive-include app/templates * recursive-include docs * # exclude file1 file2 ... #exclude manage.py # ignore dir # prune employee ``` 准备 项目根目录下use.ini ```python [uwsgi] #http = localhost:3031 #socket = 127.0.0.1:3032 # 这样也可以 socket = /tmp/%n.sock chdir = /opt/sources/cash # 包.子模块:变量 module = crash.wsgi:application stats = 127.0.0.1:9999 stats-http = uid = www-data gid = www-data #daemonize = /var/log/wsgi/%n.log #pidfile = /tmp/%n.pid processes = 2 threads = 2 master = True lazy-apps = True ``` 打包 ``` python setup.py sdist --formats=gztar,zip ``` 服务器上配置 展示zip包,准备python3.10环境 ```bash pip install uwsgi # 配置Use.ini uwsgi use.ini ``` systemd服务 ```bash # cat /etc/systemd/system/counter.service [Unit] Description=Uwsgi Counter App After=syslog.target [Service] ExecStart=/usr/local/venv/bin/uwsgi /apps/uwsgi/counter/use.ini RuntimeDirectory=uwsgi Restart=always KillSignal=SIGQUIT Type=notify StandardError=syslog NotifyAccess=all [Install] WantedBy=multi-user.target ```