├── .drone.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── _product ├── nginx.conf └── uwsgi.ini ├── db └── .gitkeep ├── deploy.ini ├── images ├── admin.jpg ├── alipay.png └── swagger.png ├── log └── .gitkeep ├── manage.py ├── media └── .gitkeep ├── requirements.txt ├── rest_backend ├── __init__.py ├── apps │ └── __init__.py ├── libs │ ├── __init__.py │ ├── accounts │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── locale │ │ │ └── zh_Hans │ │ │ │ └── LC_MESSAGES │ │ │ │ ├── django.mo │ │ │ │ └── django.po │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── backend │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py ├── settings │ ├── __init__.py │ ├── base.py │ ├── celery_local.py │ ├── celery_product.py │ ├── local.py │ └── product.py ├── urls.py ├── utils │ ├── __init__.py │ ├── database_router.py │ └── middleware.py └── wsgi.py └── third_party_app_trans ├── README.md └── django_celery_beat └── locale ├── zh-Hans └── LC_MESSAGES │ ├── django.mo │ └── django.po └── zh └── LC_MESSAGES ├── django.mo └── django.po /.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: default 3 | 4 | steps: 5 | - name: push_image 6 | image: plugins/docker 7 | settings: 8 | registry: registry.home-stack.in 9 | repo: registry.home-stack.in/rest-backend 10 | tags: 11 | - ${DRONE_TAG} 12 | - latest 13 | insecure: true 14 | when: 15 | event: 16 | - tag 17 | - deployment 18 | - name: deploy 19 | image: quay.io/honestbee/drone-kubernetes 20 | settings: 21 | namespace: demo 22 | deployment: rest-backend 23 | repo: registry.home-stack.in/rest-backend 24 | container: rest-backend 25 | tag: ${DRONE_TAG=latest} 26 | kubernetes_server: 27 | from_secret: kubernetes_server 28 | kubernetes_token: 29 | from_secret: kubernetes_token 30 | when: 31 | event: 32 | - tag 33 | - deployment 34 | - name: notify 35 | image: wuyue/drone-dingding 36 | environment: 37 | DING_DING_WEBHOOK_URL: 38 | from_secret: DING_DING_WEBHOOK_URL 39 | when: 40 | event: 41 | - tag 42 | - deployment 43 | status: 44 | - success 45 | - failure -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.sqlite3 3 | .idea -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM wuyue/python3-app:with_nginx 2 | MAINTAINER wuyue92tree@163.com 3 | 4 | COPY . /data/src 5 | COPY ./deploy.ini /etc/supervisor/conf.d/ 6 | COPY ./_product/nginx.conf /usr/local/nginx/conf/nginx.conf 7 | 8 | RUN pip install -r requirements.txt -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com 9 | 10 | RUN python manage.py collectstatic --noinput 11 | 12 | WORKDIR /data/src 13 | 14 | EXPOSE 5555 15 | EXPOSE 9001 16 | EXPOSE 80 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 wuyue 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rest_backend 2 | 3 | ## 后台api接口模板 4 | 5 | ### admin管理页 6 | ![admin](./images/admin.jpg) 7 | 8 | 9 | ### swagger-ui页 10 | ![swagger](./images/swagger.png) 11 | 12 | ## 基础依赖 13 | 14 | - python3.6+ 15 | 16 | - django2.2 17 | 18 | ## 初始化 19 | 20 | ``` 21 | git clone https://github.com/wuyue92tree/rest_backend.git 22 | 23 | cd rest_backend 24 | 25 | pip install -r requirements.txt 26 | 27 | python manage.py migrate 28 | 29 | python manage.py createsuperuser 30 | 31 | python manage.py runserver 32 | ``` 33 | 34 | ## 启动 35 | 36 | 后台地址:http://127.0.0.1:8000/ 37 | 38 | API地址: http://127.0.0.1:8000/api/docs/ 39 | 40 | 41 | ## docker部署上线 42 | 43 | ``` 44 | git clone https://github.com/wuyue92tree/rest_backend.git 45 | 46 | cd rest_backend 47 | 48 | docker build -t rest_backend . 49 | 50 | docker run -tid -v :/data/src/log -p 80:80 rest_backend 51 | ``` 52 | 53 | ## demo 54 | 55 | [http://django-demo.antio.top/](http://django-demo.antio.top/) 56 | 57 | ## 捐赠 58 | 59 |

60 | 61 |    title 62 | 63 |

64 | -------------------------------------------------------------------------------- /_product/nginx.conf: -------------------------------------------------------------------------------- 1 | #user nobody; 2 | worker_processes 4; 3 | 4 | #pid logs/nginx.pid; 5 | 6 | events { 7 | worker_connections 1024; 8 | } 9 | 10 | 11 | http { 12 | include mime.types; 13 | default_type application/octet-stream; 14 | 15 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 16 | # '$status $body_bytes_sent "$http_referer" ' 17 | # '"$http_user_agent" "$http_x_forwarded_for"'; 18 | 19 | #access_log logs/access.log main; 20 | 21 | sendfile on; 22 | #tcp_nopush on; 23 | 24 | #keepalive_timeout 0; 25 | keepalive_timeout 65; 26 | 27 | #gzip on; 28 | server { 29 | # the port your site will be served on 30 | listen 80; 31 | # the domain name it will serve for 32 | server_name localhost; # substitute your machine's IP address or FQDN 33 | charset utf-8; 34 | 35 | access_log /data/src/log/access_log; 36 | error_log /data/src/log/error_log; 37 | 38 | # max upload size 39 | client_max_body_size 75M; # adjust to taste 40 | 41 | # Django media 42 | location /media { 43 | alias /data/src/media; # your Django project's media files - amend as required 44 | } 45 | 46 | location /static { 47 | alias /data/src/static; # your Django project's static files - amend as required 48 | 49 | } 50 | 51 | # Finally, send all non-media requests to the Django server. 52 | location / { 53 | uwsgi_pass 127.0.0.1:3031; 54 | include /usr/local/nginx/conf/uwsgi_params; # the uwsgi_params file you installed 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /_product/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | socket = 0.0.0.0:3031 3 | chdir = . 4 | module = rest_backend.wsgi 5 | master = true 6 | processes = 4 7 | threads = 2 8 | stats = 0.0.0.0:9191 -------------------------------------------------------------------------------- /db/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/db/.gitkeep -------------------------------------------------------------------------------- /deploy.ini: -------------------------------------------------------------------------------- 1 | [program:uwsgi] 2 | directory = /data/src ; 程序的启动目录 3 | command = uwsgi /data/src/_product/uwsgi.ini ; 启动命令,可以看出与手动在命令行启动的命令是一样的 4 | autostart = true ; 在 supervisord 启动的时候也自动启动 5 | startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了 6 | autorestart = true ; 程序异常退出后自动重启 7 | startretries = 3 ; 启动失败自动重试次数,默认是 3 8 | ; user = root ; 用哪个用户启动 9 | redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false 10 | stdout_logfile_maxbytes = 20MB ; stdout 日志文件大小,默认 50MB 11 | stdout_logfile_backups = 20 ; stdout 日志文件备份数 12 | ; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件) 13 | stdout_logfile = /data/src/log/uwsgi_stdout.log 14 | 15 | [program:nginx] 16 | directory = /data/src ; 程序的启动目录 17 | command = /usr/local/nginx/sbin/nginx -g 'daemon off;' ; 启动命令,可以看出与手动在命令行启动的命令是一样的 18 | autostart = true ; 在 supervisord 启动的时候也自动启动 19 | startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了 20 | autorestart = true ; 程序异常退出后自动重启 21 | startretries = 3 ; 启动失败自动重试次数,默认是 3 22 | ; user = root ; 用哪个用户启动 23 | redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false 24 | stdout_logfile_maxbytes = 20MB ; stdout 日志文件大小,默认 50MB 25 | stdout_logfile_backups = 20 ; stdout 日志文件备份数 26 | ; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件) 27 | stdout_logfile = /data/src/log/nginx_stdout.log 28 | 29 | [program:celery_flower] 30 | directory = /data/src ; 程序的启动目录 31 | command = celery -A rest_backend.settings.celery_product flower -l info --persistent=True --db=./db/flower ; 启动命令,可以看出与手动在命令行启动的命令是一样的 32 | autostart = true ; 在 supervisord 启动的时候也自动启动 33 | startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了 34 | autorestart = true ; 程序异常退出后自动重启 35 | startretries = 3 ; 启动失败自动重试次数,默认是 3 36 | ; user = root ; 用哪个用户启动 37 | redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false 38 | stdout_logfile_maxbytes = 20MB ; stdout 日志文件大小,默认 50MB 39 | stdout_logfile_backups = 20 ; stdout 日志文件备份数 40 | ; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件) 41 | stdout_logfile = /data/src/log/celery_flower_stdout.log 42 | 43 | [program:celery] 44 | directory = /data/src ; 程序的启动目录 45 | command = celery -A rest_backend.settings.celery_product worker -l info -B ; 启动命令,可以看出与手动在命令行启动的命令是一样的 46 | autostart = true ; 在 supervisord 启动的时候也自动启动 47 | startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了 48 | autorestart = true ; 程序异常退出后自动重启 49 | startretries = 3 ; 启动失败自动重试次数,默认是 3 50 | ; user = root ; 用哪个用户启动 51 | redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false 52 | stdout_logfile_maxbytes = 20MB ; stdout 日志文件大小,默认 50MB 53 | stdout_logfile_backups = 20 ; stdout 日志文件备份数 54 | ; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件) 55 | stdout_logfile = /data/src/log/celery_stdout.log -------------------------------------------------------------------------------- /images/admin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/images/admin.jpg -------------------------------------------------------------------------------- /images/alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/images/alipay.png -------------------------------------------------------------------------------- /images/swagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/images/swagger.png -------------------------------------------------------------------------------- /log/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/log/.gitkeep -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rest_backend.settings.local") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /media/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/media/.gitkeep -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==2.2.4 2 | django-celery-beat==1.3.0 3 | django-cors-headers==2.2.0 4 | django-debug-toolbar==1.9.1 5 | django-rest-swagger==2.2.0 6 | djangorestframework==3.9.1 7 | djangorestframework-jwt==1.11.0 8 | django-filter==2.0.0 9 | Pillow==5.1.0 10 | uwsgi==2.0.15 11 | redis==2.10.6 12 | flower==0.9.2 13 | tornado==5.1.1 14 | django-treebeard==4.3 15 | django-adminlte-ui==1.4.0 16 | -------------------------------------------------------------------------------- /rest_backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/__init__.py -------------------------------------------------------------------------------- /rest_backend/apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/apps/__init__.py -------------------------------------------------------------------------------- /rest_backend/libs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/libs/__init__.py -------------------------------------------------------------------------------- /rest_backend/libs/accounts/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = 'rest_backend.libs.accounts.apps.AccountsConfig' 2 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth.admin import UserAdmin as BaseUserAdmin 3 | from .models import User 4 | from django.utils.translation import ugettext_lazy as _ 5 | # Register your models here. 6 | 7 | 8 | @admin.register(User) 9 | class UserAdmin(BaseUserAdmin): 10 | fieldsets = ( 11 | (None, {'fields': ('username', 'password')}), 12 | (_('Personal info'), {'fields': ('nickname', 'first_name', 'last_name', 13 | 'phone', 'email', 'gender', 14 | 'head_avatar', 'birthday', 15 | 'description')}), 16 | (_('Permissions'), {'fields': ('is_active', 'is_superuser', 17 | 'groups', 'user_permissions')}), 18 | (_('Important dates'), {'fields': ('last_login', 'date_joined')}), 19 | ) 20 | add_fieldsets = ( 21 | (None, { 22 | 'classes': ('wide',), 23 | 'fields': ('username', 'password1', 'password2'), 24 | }), 25 | ) 26 | list_display = ('username', 'email', 'nickname', 'phone', 'is_active', 27 | 'last_login') 28 | list_filter = ('is_active', 'is_staff', 'is_superuser') 29 | search_fields = ('username', 'nickname', 'phone', 'email') 30 | ordering = ('username',) 31 | filter_horizontal = ('groups', 'user_permissions',) 32 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | from django.utils.translation import gettext_lazy as _ 5 | 6 | __all__ = ['AccountsConfig'] 7 | 8 | 9 | class AccountsConfig(AppConfig): 10 | name = 'rest_backend.libs.accounts' 11 | label = 'accounts' 12 | verbose_name = _('User Center') 13 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/locale/zh_Hans/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/libs/accounts/locale/zh_Hans/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /rest_backend/libs/accounts/locale/zh_Hans/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2019-07-07 13:20+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0;\n" 20 | 21 | #: admin.py:12 22 | msgid "Personal info" 23 | msgstr "" 24 | 25 | #: admin.py:16 26 | msgid "Permissions" 27 | msgstr "" 28 | 29 | #: admin.py:18 30 | msgid "Important dates" 31 | msgstr "" 32 | 33 | #: apps.py:12 34 | msgid "User Center" 35 | msgstr "用户中心" 36 | 37 | #: models.py:10 38 | msgid "unknown" 39 | msgstr "未知" 40 | 41 | #: models.py:11 42 | msgid "male" 43 | msgstr "男" 44 | 45 | #: models.py:12 46 | msgid "female" 47 | msgstr "女" 48 | 49 | #: models.py:14 50 | msgid "nickname" 51 | msgstr "昵称" 52 | 53 | #: models.py:15 54 | msgid "phone" 55 | msgstr "手机号" 56 | 57 | #: models.py:20 58 | msgid "head_avatar" 59 | msgstr "头像" 60 | 61 | #: models.py:21 62 | #, fuzzy 63 | #| msgid "header_oauth_avatar" 64 | msgid "head_oauth_avatar" 65 | msgstr "oauth头像" 66 | 67 | #: models.py:22 68 | msgid "description" 69 | msgstr "个人简介" 70 | 71 | #: models.py:23 72 | msgid "gender" 73 | msgstr "性别" 74 | 75 | #: models.py:24 76 | msgid "birthday" 77 | msgstr "生日" 78 | 79 | #: models.py:25 80 | msgid "activate_key" 81 | msgstr "激活码" 82 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.2 on 2018-04-22 04:14 2 | 3 | import django.contrib.auth.models 4 | import django.contrib.auth.validators 5 | from django.db import migrations, models 6 | import django.utils.timezone 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ('auth', '0009_alter_user_last_name_max_length'), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='User', 20 | fields=[ 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('password', models.CharField(max_length=128, verbose_name='password')), 23 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 24 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), 25 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), 26 | ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), 27 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), 28 | ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), 29 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), 30 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), 31 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), 32 | ('nickname', models.CharField(blank=True, max_length=255, verbose_name='nickname')), 33 | ('phone', models.BigIntegerField(blank=True, null=True, verbose_name='phone')), 34 | ('head_avatar', models.ImageField(blank=True, default='./avatars/default.png', upload_to='./avatars', verbose_name='head_avatar')), 35 | ('head_oauth_avatar', models.URLField(blank=True, verbose_name='head_oauth_avatar')), 36 | ('description', models.TextField(blank=True, verbose_name='description')), 37 | ('gender', models.IntegerField(blank=True, choices=[(0, 'unknown'), (1, 'male'), (2, 'female')], null=True, verbose_name='gender')), 38 | ('birthday', models.DateField(default=django.utils.timezone.now, verbose_name='birthday')), 39 | ('activate_key', models.SlugField(blank=True, max_length=255, verbose_name='activate_key')), 40 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), 41 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), 42 | ], 43 | options={ 44 | 'verbose_name': 'user', 45 | 'verbose_name_plural': 'users', 46 | 'abstract': False, 47 | }, 48 | managers=[ 49 | ('objects', django.contrib.auth.models.UserManager()), 50 | ], 51 | ), 52 | ] 53 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/libs/accounts/migrations/__init__.py -------------------------------------------------------------------------------- /rest_backend/libs/accounts/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django.db import models 3 | from django.contrib.auth.models import AbstractUser 4 | from django.utils.translation import ugettext_lazy as _ 5 | from django.utils import timezone 6 | 7 | 8 | class User(AbstractUser): 9 | GENDER_CHOICE = ( 10 | (0, _('unknown')), 11 | (1, _('male')), 12 | (2, _('female')), 13 | ) 14 | nickname = models.CharField(max_length=255, blank=True, verbose_name=_('nickname')) 15 | phone = models.BigIntegerField(blank=True, null=True, verbose_name=_('phone')) 16 | head_avatar = models.ImageField( 17 | upload_to='./avatars', 18 | default="./avatars/default.png", 19 | blank=True, 20 | verbose_name=_('head_avatar')) 21 | head_oauth_avatar = models.URLField(blank=True, verbose_name=_('head_oauth_avatar')) 22 | description = models.TextField(blank=True, verbose_name=_('description')) 23 | gender = models.IntegerField(blank=True, null=True, choices=GENDER_CHOICE, verbose_name=_('gender')) 24 | birthday = models.DateField(default=timezone.now, verbose_name=_('birthday')) 25 | activate_key = models.SlugField(max_length=255, blank=True, verbose_name=_('activate_key')) 26 | 27 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/urls.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: wuyue 5 | @contact: wuyue92tree@163.com 6 | @software: IntelliJ IDEA 7 | @file: urls.py 8 | @create at: 2018-09-09 21:55 9 | 10 | 这一行开始写关于本文件的说明与解释 11 | """ 12 | 13 | from django.urls import path, include 14 | from .views import * 15 | from rest_framework import routers 16 | # 17 | # router = routers.DefaultRouter() 18 | # router.register('profile', ProfileApiView.as_view()) 19 | 20 | urlpatterns = [ 21 | path('profile/', ProfileApiView.as_view()), 22 | path('initToken/', InitToken.as_view()), 23 | path('getToken/', GetToken.as_view()) 24 | ] 25 | -------------------------------------------------------------------------------- /rest_backend/libs/accounts/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.shortcuts import render 5 | from rest_framework import generics 6 | from rest_framework import serializers 7 | from rest_framework.permissions import DjangoModelPermissions 8 | from rest_framework.response import Response 9 | from rest_framework import status 10 | from .models import User 11 | from rest_framework.authtoken.models import Token 12 | 13 | 14 | # Create your views here. 15 | 16 | 17 | class ProfileSerializer(serializers.ModelSerializer): 18 | """ 19 | 序列化用户信息 20 | """ 21 | 22 | class Meta: 23 | model = User 24 | # fields = '__all__' 25 | fields = ( 26 | 'username', 'email', 'phone', 'nickname', 'is_superuser', 27 | 'is_staff', 28 | 'last_login', 'date_joined') 29 | read_only_fields = ( 30 | 'username', 'is_superuser', 'is_staff', 'last_login', 31 | 'date_joined') 32 | 33 | # def update(self, instance, validated_data): 34 | 35 | 36 | class ProfileApiView(generics.GenericAPIView): 37 | """ 38 | 用户信息接口 39 | parameters: 40 | - name: data 41 | type: json 42 | required: true 43 | location: form 44 | """ 45 | serializer_class = ProfileSerializer 46 | filter_backends = None 47 | pagination_class = None 48 | 49 | def get(self, request): 50 | queryset = User.objects.get(id=request.user.id) 51 | serializer = self.get_serializer(queryset) 52 | return Response(serializer.data) 53 | 54 | def post(self, request): 55 | instance = User.objects.get(id=request.user.id) 56 | serializer = ProfileSerializer(data=request.data) 57 | if serializer.is_valid(): 58 | serializer.update(instance=instance, 59 | validated_data=serializer.validated_data) 60 | return Response(serializer.data, status=status.HTTP_200_OK) 61 | else: 62 | return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR) 63 | 64 | 65 | class GetToken(generics.GenericAPIView): 66 | """ 67 | 获取Token令牌 68 | """ 69 | queryset = Token.objects.all() 70 | permission_classes = [DjangoModelPermissions] 71 | pagination_class = None 72 | 73 | def get(self, request): 74 | try: 75 | access_token = self.get_queryset().get(user_id=request.user.id).key 76 | return Response({'token': access_token}) 77 | except Token.DoesNotExist: 78 | return Response({}) 79 | except Exception as e: 80 | return Response({'系统异常: {}'.format(str(e))}, 81 | status=status.HTTP_500_INTERNAL_SERVER_ERROR) 82 | 83 | 84 | class InitToken(generics.GenericAPIView): 85 | """ 86 | 初始化Token令牌 87 | """ 88 | queryset = Token.objects.all() 89 | pagination_class = None 90 | permission_classes = [DjangoModelPermissions] 91 | 92 | def get(self, request): 93 | try: 94 | if len(Token.objects.filter(user_id=request.user.id)) > 0: 95 | item = Token.objects.get(user_id=request.user.id) 96 | item.delete() 97 | new_item = Token.objects.create(user_id=request.user.id) 98 | new_item.save() 99 | return Response({'token': new_item.key}) 100 | except Exception as e: 101 | return Response({'系统异常: {}'.format(str(e))}, 102 | status=status.HTTP_500_INTERNAL_SERVER_ERROR) 103 | -------------------------------------------------------------------------------- /rest_backend/libs/backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/libs/backend/__init__.py -------------------------------------------------------------------------------- /rest_backend/libs/backend/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /rest_backend/libs/backend/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class LibsConfig(AppConfig): 5 | name = 'backend' 6 | -------------------------------------------------------------------------------- /rest_backend/libs/backend/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/libs/backend/migrations/__init__.py -------------------------------------------------------------------------------- /rest_backend/libs/backend/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /rest_backend/libs/backend/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /rest_backend/libs/backend/urls.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: wuyue 5 | @contact: wuyue92tree@163.com 6 | @software: PyCharm 7 | @file: urls.py 8 | @create at: 2018-04-15 17:58 9 | 10 | 这一行开始写关于本文件的说明与解释 11 | """ 12 | 13 | from django.urls import path, include 14 | from rest_framework_swagger.views import get_swagger_view 15 | from rest_framework import routers 16 | from rest_framework_jwt.views import obtain_jwt_token 17 | 18 | schema_view = get_swagger_view(title='Project API') 19 | 20 | router = routers.DefaultRouter() 21 | 22 | app_name = 'backend' 23 | 24 | urlpatterns = [ 25 | path('auth/login/', obtain_jwt_token, name='token-login'), 26 | path('docs/', schema_view), 27 | 28 | # add api here 29 | path('account/', include('rest_backend.libs.accounts.urls')), 30 | ] 31 | -------------------------------------------------------------------------------- /rest_backend/libs/backend/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /rest_backend/settings/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/settings/__init__.py -------------------------------------------------------------------------------- /rest_backend/settings/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for rest_backend project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.1.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.1/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname( 17 | os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '_s8g4(beq1k%lnh43)wpvg_zecgl5_7$m-xng_z@%klc+z)nvt' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | # Application definition 31 | 32 | INSTALLED_APPS = [ 33 | 'adminlteui', 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | # treebeard 41 | 'treebeard', 42 | # debug工具 43 | 'debug_toolbar', 44 | # 跨域 45 | 'corsheaders', 46 | # rest接口框架 47 | 'rest_framework', 48 | 'rest_framework.authtoken', 49 | # rest文档swagger 50 | 'rest_framework_swagger', 51 | # celery 52 | 'django_celery_beat', 53 | 'rest_backend.libs.backend', 54 | 'rest_backend.libs.accounts', 55 | ] 56 | 57 | MIDDLEWARE = [ 58 | 'django.middleware.security.SecurityMiddleware', 59 | 'django.contrib.sessions.middleware.SessionMiddleware', 60 | 61 | 'django.middleware.common.CommonMiddleware', 62 | 'django.middleware.csrf.CsrfViewMiddleware', 63 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 64 | 'django.contrib.messages.middleware.MessageMiddleware', 65 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 66 | # token参数认证 67 | 'rest_backend.utils.middleware.TokenAuthMiddleware', 68 | # 跨域 69 | 'corsheaders.middleware.CorsMiddleware', 70 | # 激活locale 71 | 'django.middleware.locale.LocaleMiddleware', 72 | 'debug_toolbar.middleware.DebugToolbarMiddleware', 73 | ] 74 | 75 | ROOT_URLCONF = 'rest_backend.urls' 76 | 77 | # 自定义用户注册模块 78 | AUTH_USER_MODEL = 'accounts.User' 79 | 80 | # session过期时间设置 81 | SESSION_COOKIE_AGE = 3600 * 24 82 | 83 | TEMPLATES = [ 84 | { 85 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 86 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 87 | 'APP_DIRS': True, 88 | 'OPTIONS': { 89 | 'context_processors': [ 90 | 'django.template.context_processors.debug', 91 | 'django.template.context_processors.request', 92 | 'django.contrib.auth.context_processors.auth', 93 | 'django.contrib.messages.context_processors.messages', 94 | ], 95 | }, 96 | }, 97 | ] 98 | 99 | WSGI_APPLICATION = 'rest_backend.wsgi.application' 100 | 101 | # Database 102 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases 103 | 104 | DATABASES = { 105 | 'default': { 106 | 'ENGINE': 'django.db.backends.sqlite3', 107 | 'NAME': os.path.join(BASE_DIR, 'db/db.sqlite3'), 108 | } 109 | } 110 | 111 | # 添加路由 112 | DATABASE_ROUTERS = ['rest_backend.utils.database_router.DatabaseAppsRouter'] 113 | DATABASE_APPS_MAPPING = { 114 | # example: 115 | # 'app_name':'database_name', 116 | 'accounts': 'default', 117 | } 118 | 119 | # Password validation 120 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators 121 | 122 | AUTH_PASSWORD_VALIDATORS = [ 123 | { 124 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 125 | }, 126 | { 127 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 128 | }, 129 | { 130 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 131 | }, 132 | { 133 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 134 | }, 135 | ] 136 | 137 | # Internationalization 138 | # https://docs.djangoproject.com/en/2.1/topics/i18n/ 139 | 140 | LANGUAGES = ( 141 | ('zh-hans', '简体中文'), 142 | ('en', 'English') 143 | ) 144 | 145 | 146 | LANGUAGE_CODE = 'zh-hans' 147 | 148 | TIME_ZONE = 'Asia/Shanghai' 149 | 150 | USE_I18N = True 151 | 152 | USE_L10N = True 153 | 154 | USE_TZ = True 155 | 156 | # Static files (CSS, JavaScript, Images) 157 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ 158 | 159 | STATIC_URL = '/static/' 160 | 161 | STATIC_ROOT = os.path.join(BASE_DIR, 'static') 162 | 163 | 164 | MEDIA_URL = '/media/' 165 | 166 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 167 | 168 | 169 | # REST_FRAMEWORK 170 | 171 | REST_FRAMEWORK = { 172 | 'DEFAULT_AUTHENTICATION_CLASSES': [ 173 | 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 174 | 'rest_framework.authentication.TokenAuthentication', 175 | 'rest_framework.authentication.BasicAuthentication', 176 | 'rest_framework.authentication.SessionAuthentication', 177 | ], 178 | 'DEFAULT_PERMISSION_CLASSES': [ 179 | 'rest_framework.permissions.IsAuthenticated', 180 | ], 181 | 'DEFAULT_FILTER_BACKENDS': [ 182 | 'django_filters.rest_framework.DjangoFilterBackend', 183 | ], 184 | 'DEFAULT_PAGINATION_CLASS': 185 | 'rest_framework.pagination.LimitOffsetPagination', 186 | 'PAGE_SIZE': 10 187 | } 188 | 189 | # SWAGGER 190 | 191 | LOGIN_URL = 'rest_framework:login' 192 | LOGOUT_URL = 'rest_framework:logout' 193 | 194 | SWAGGER_SETTINGS = { 195 | 'SECURITY_DEFINITIONS': { 196 | 'basic': { 197 | 'type': 'basic' 198 | } 199 | }, 200 | 'JSON_EDITOR': True 201 | } 202 | 203 | # Debug Tool Bar 204 | 205 | INTERNAL_IPS = ('127.0.0.1',) 206 | 207 | DEBUG_TOOLBAR_PANELS = [ 208 | 'debug_toolbar.panels.versions.VersionsPanel', 209 | 'debug_toolbar.panels.timer.TimerPanel', 210 | 'debug_toolbar.panels.settings.SettingsPanel', 211 | 'debug_toolbar.panels.headers.HeadersPanel', 212 | 'debug_toolbar.panels.request.RequestPanel', 213 | 'debug_toolbar.panels.sql.SQLPanel', 214 | 'debug_toolbar.panels.staticfiles.StaticFilesPanel', 215 | 'debug_toolbar.panels.templates.TemplatesPanel', 216 | 'debug_toolbar.panels.cache.CachePanel', 217 | 'debug_toolbar.panels.signals.SignalsPanel', 218 | 'debug_toolbar.panels.logging.LoggingPanel', 219 | 'debug_toolbar.panels.redirects.RedirectsPanel', 220 | ] 221 | 222 | DEBUG_TOOLBAR_CONFIG = { 223 | 'JQUERY_URL': r"http://code.jquery.com/jquery-2.1.1.min.js" 224 | } 225 | 226 | # corsheaders 227 | # https://github.com/ottoyiu/django-cors-headers/ 228 | 229 | CORS_ORIGIN_ALLOW_ALL = True 230 | 231 | # CORS_ORIGIN_WHITELIST = ( 232 | # 'google.com', 233 | # 'hostname.example.com', 234 | # 'localhost:8000', 235 | # '127.0.0.1:9000' 236 | # ) 237 | 238 | 239 | CELERYBEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler' 240 | CELERY_ACCEPT_CONTENT = ['json'] 241 | CELERY_TASK_SERIALIZER = 'json' 242 | CELERY_RESULT_SERIALIZER = 'json' 243 | CELERY_TIMEZONE = TIME_ZONE 244 | 245 | LOCALE_PATHS = ( 246 | os.path.join(BASE_DIR, 'third_party_app_trans/django_celery_beat/locale'), 247 | ) 248 | -------------------------------------------------------------------------------- /rest_backend/settings/celery_local.py: -------------------------------------------------------------------------------- 1 | import os 2 | from django.conf import settings 3 | from celery import Celery 4 | 5 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rest_backend.settings.local') 6 | 7 | celery_app = Celery('tasks') 8 | celery_app.config_from_object(settings) 9 | celery_app.autodiscover_tasks() 10 | -------------------------------------------------------------------------------- /rest_backend/settings/celery_product.py: -------------------------------------------------------------------------------- 1 | import os 2 | from django.conf import settings 3 | from celery import Celery 4 | 5 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rest_backend.settings.product') 6 | 7 | celery_app = Celery('tasks') 8 | celery_app.config_from_object(settings) 9 | celery_app.autodiscover_tasks() 10 | -------------------------------------------------------------------------------- /rest_backend/settings/local.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: wuyue 5 | @contact: wuyue92tree@163.com 6 | @software: PyCharm 7 | @file: local.py.py 8 | @create at: 2018-04-15 17:37 9 | 10 | 这一行开始写关于本文件的说明与解释 11 | """ 12 | 13 | 14 | from .base import * 15 | 16 | DEBUG = True 17 | -------------------------------------------------------------------------------- /rest_backend/settings/product.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: wuyue 5 | @contact: wuyue92tree@163.com 6 | @software: PyCharm 7 | @file: product.py.py 8 | @create at: 2018-04-15 17:37 9 | 10 | 这一行开始写关于本文件的说明与解释 11 | """ 12 | 13 | from .base import * 14 | 15 | ALLOWED_HOSTS = ['*'] 16 | 17 | DEBUG = False 18 | 19 | # celery 20 | # BROKER_URL = 'redis://127.0.0.1:6379/1' 21 | # CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379' 22 | 23 | ADMINLTE_SETTINGS = { 24 | 'demo': False, 25 | 'search_form': False 26 | } 27 | -------------------------------------------------------------------------------- /rest_backend/urls.py: -------------------------------------------------------------------------------- 1 | """rest_backend URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.conf import settings 18 | from django.urls import path, include 19 | from django.views.generic import RedirectView 20 | from django.conf.urls.i18n import i18n_patterns 21 | 22 | urlpatterns = [ 23 | 24 | ] 25 | 26 | urlpatterns += i18n_patterns( 27 | path('admin/', admin.site.urls), 28 | path('', RedirectView.as_view(url='/admin/')), 29 | path('', include('rest_framework.urls', namespace='rest_framework')), 30 | path('api/', include('rest_backend.libs.backend.urls', namespace='api')) 31 | ) 32 | 33 | if settings.DEBUG: 34 | import debug_toolbar 35 | 36 | urlpatterns = [ 37 | path('__debug__/', include(debug_toolbar.urls)), 38 | ] + urlpatterns 39 | -------------------------------------------------------------------------------- /rest_backend/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/rest_backend/utils/__init__.py -------------------------------------------------------------------------------- /rest_backend/utils/database_router.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: wuyue 5 | @contact: wuyue92tree@163.com 6 | @software: PyCharm 7 | @file: database_router.py 8 | @create at: 2018-04-22 12:53 9 | 10 | 这一行开始写关于本文件的说明与解释 11 | """ 12 | 13 | from django.conf import settings 14 | 15 | DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING 16 | 17 | 18 | class DatabaseAppsRouter(object): 19 | """ 20 | A router to control all database operations on models for different 21 | databases. 22 | In case an app is not set in settings.DATABASE_APPS_MAPPING, the router 23 | will fallback to the `default` database. 24 | Settings example: 25 | DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'} 26 | """ 27 | 28 | def db_for_read(self, model, **hints): 29 | """"Point all read operations to the specific database.""" 30 | if model._meta.app_label in DATABASE_MAPPING: 31 | return DATABASE_MAPPING[model._meta.app_label] 32 | return None 33 | 34 | def db_for_write(self, model, **hints): 35 | """Point all write operations to the specific database.""" 36 | if model._meta.app_label in DATABASE_MAPPING: 37 | return DATABASE_MAPPING[model._meta.app_label] 38 | return None 39 | 40 | def allow_relation(self, obj1, obj2, **hints): 41 | """Allow any relation between apps that use the same database.""" 42 | db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label) 43 | db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label) 44 | if db_obj1 and db_obj2: 45 | if db_obj1 == db_obj2: 46 | return True 47 | else: 48 | return False 49 | return None 50 | 51 | def allow_syncdb(self, db, model): 52 | """Make sure that apps only appear in the related database.""" 53 | 54 | if db in DATABASE_MAPPING.values(): 55 | return DATABASE_MAPPING.get(model._meta.app_label) == db 56 | elif model._meta.app_label in DATABASE_MAPPING: 57 | return False 58 | return None 59 | -------------------------------------------------------------------------------- /rest_backend/utils/middleware.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: wuyue 5 | @contact: wuyue92tree@163.com 6 | @software: PyCharm 7 | @file: middleware.py 8 | @create at: 2018-07-28 23:05 9 | 10 | 这一行开始写关于本文件的说明与解释 11 | """ 12 | 13 | from django.utils.deprecation import MiddlewareMixin 14 | 15 | 16 | class TokenAuthMiddleware(MiddlewareMixin): 17 | def process_request(self, request): 18 | if request.GET.get('token'): 19 | request.META['HTTP_AUTHORIZATION'] = 'Token %s' % request.GET.get( 20 | 'token') 21 | -------------------------------------------------------------------------------- /rest_backend/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for rest_backend project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rest_backend.settings.product") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /third_party_app_trans/README.md: -------------------------------------------------------------------------------- 1 | # 第三方app翻译 2 | 3 | ### settings.py中添加LOCALE_PATHS,不添加makemessages无法工作 4 | 5 | ``` 6 | LOCALE_PATHS = ( 7 | os.path.join(BASE_DIR, 'locale'), 8 | ) 9 | 10 | # mkdir [BASE_DIR]/locale 11 | ``` 12 | 13 | 14 | ### 创建待翻译第三方app软连接到项目目录 15 | 16 | ``` 17 | ln -s ~/.virtualenvs//lib/python3.4/site-packages/ ./ 18 | ``` 19 | 20 | ### 生成`.po`文件 21 | 22 | ``` 23 | ./manage.py makemessages -s -l zh 24 | ``` 25 | 26 | ### 创建第三方app翻译文件存放目录,并将生成的locale文件夹转移到存放目录 27 | 28 | ```$xslt 29 | mkdir third_party_app_trans/ 30 | 31 | cp -r /locale third_party_app_trans// 32 | 33 | rm 34 | 35 | ``` 36 | 37 | ### 将第三方app翻译文件路径加入到settings.py中 38 | 39 | ```$xslt 40 | LOCALE_PATHS = ( 41 | os.path.join(BASE_DIR, 'locale'), 42 | os.path.join(BASE_DIR, 'third_party_app_trans//locale'), 43 | ) 44 | ``` 45 | 46 | ### 修改并编译 47 | 48 | ```$xslt 49 | vi third_party_app_trans//locale/zh/django.po 50 | 51 | ./manage.py compilemessages 52 | ``` -------------------------------------------------------------------------------- /third_party_app_trans/django_celery_beat/locale/zh-Hans/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/third_party_app_trans/django_celery_beat/locale/zh-Hans/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /third_party_app_trans/django_celery_beat/locale/zh-Hans/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2019-03-12 11:38+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: django_celery_beat/admin.py:71 21 | msgid "Task (registered)" 22 | msgstr "任务(已注册)" 23 | 24 | #: django_celery_beat/admin.py:75 25 | msgid "Task (custom)" 26 | msgstr "任务(自定义)" 27 | 28 | #: django_celery_beat/admin.py:92 29 | msgid "Need name of task" 30 | msgstr "" 31 | 32 | #: django_celery_beat/admin.py:103 33 | #, python-format 34 | msgid "Unable to parse JSON: %s" 35 | msgstr "无法解析的JSON串: %s" 36 | 37 | #: django_celery_beat/admin.py:162 38 | #, python-brace-format 39 | msgid "{0} task{1} {2} successfully {3}" 40 | msgstr "{0} 任务{1} {2} 成功 {3}" 41 | 42 | #: django_celery_beat/admin.py:165 django_celery_beat/admin.py:208 43 | msgid "was,were" 44 | msgstr "" 45 | 46 | #: django_celery_beat/admin.py:174 47 | msgid "Enable selected tasks" 48 | msgstr "启用已选中的任务" 49 | 50 | #: django_celery_beat/admin.py:180 51 | msgid "Disable selected tasks" 52 | msgstr "禁用已选中的任务" 53 | 54 | #: django_celery_beat/admin.py:192 55 | msgid "Toggle activity of selected tasks" 56 | msgstr "" 57 | 58 | #: django_celery_beat/admin.py:205 59 | #, python-brace-format 60 | msgid "{0} task{1} {2} successfully run" 61 | msgstr "{0} 任务{1} {2} 启动成功" 62 | 63 | #: django_celery_beat/admin.py:211 64 | msgid "Run selected tasks" 65 | msgstr "执行已选中的任务" 66 | 67 | #: django_celery_beat/apps.py:15 68 | msgid "Periodic Tasks" 69 | msgstr "任务调度系统" 70 | 71 | #: django_celery_beat/models.py:27 72 | msgid "Days" 73 | msgstr "日" 74 | 75 | #: django_celery_beat/models.py:28 76 | msgid "Hours" 77 | msgstr "时" 78 | 79 | #: django_celery_beat/models.py:29 80 | msgid "Minutes" 81 | msgstr "分" 82 | 83 | #: django_celery_beat/models.py:30 84 | msgid "Seconds" 85 | msgstr "秒" 86 | 87 | #: django_celery_beat/models.py:31 88 | msgid "Microseconds" 89 | msgstr "毫秒" 90 | 91 | #: django_celery_beat/models.py:47 92 | msgid "event" 93 | msgstr "" 94 | 95 | #: django_celery_beat/models.py:50 96 | msgid "latitude" 97 | msgstr "" 98 | 99 | #: django_celery_beat/models.py:53 100 | msgid "longitude" 101 | msgstr "" 102 | 103 | #: django_celery_beat/models.py:59 104 | msgid "solar event" 105 | msgstr "solar" 106 | 107 | #: django_celery_beat/models.py:60 108 | msgid "solar events" 109 | msgstr "Solar配置" 110 | 111 | #: django_celery_beat/models.py:104 112 | msgid "every" 113 | msgstr "每" 114 | 115 | #: django_celery_beat/models.py:106 116 | msgid "period" 117 | msgstr "日期单位" 118 | 119 | #: django_celery_beat/models.py:112 django_celery_beat/models.py:257 120 | msgid "interval" 121 | msgstr "时间区间" 122 | 123 | #: django_celery_beat/models.py:113 124 | msgid "intervals" 125 | msgstr "时间区间配置" 126 | 127 | #: django_celery_beat/models.py:136 128 | #, python-brace-format 129 | msgid "every {0.period_singular}" 130 | msgstr "" 131 | 132 | #: django_celery_beat/models.py:137 133 | #, python-brace-format 134 | msgid "every {0.every} {0.period}" 135 | msgstr "" 136 | 137 | #: django_celery_beat/models.py:156 138 | msgid "minute" 139 | msgstr "" 140 | 141 | #: django_celery_beat/models.py:160 142 | msgid "hour" 143 | msgstr "" 144 | 145 | #: django_celery_beat/models.py:164 146 | msgid "day of week" 147 | msgstr "" 148 | 149 | #: django_celery_beat/models.py:168 150 | msgid "day of month" 151 | msgstr "" 152 | 153 | #: django_celery_beat/models.py:172 154 | msgid "month of year" 155 | msgstr "" 156 | 157 | #: django_celery_beat/models.py:181 django_celery_beat/models.py:261 158 | msgid "crontab" 159 | msgstr "" 160 | 161 | #: django_celery_beat/models.py:182 162 | msgid "crontabs" 163 | msgstr "Crontab配置" 164 | 165 | #: django_celery_beat/models.py:251 166 | msgid "name" 167 | msgstr "" 168 | 169 | #: django_celery_beat/models.py:252 170 | msgid "Useful description" 171 | msgstr "有益的描述" 172 | 173 | #: django_celery_beat/models.py:254 174 | msgid "task name" 175 | msgstr "任务名称" 176 | 177 | #: django_celery_beat/models.py:261 178 | msgid "Use one of interval/crontab" 179 | msgstr "使用interval/crontab中的一个" 180 | 181 | #: django_celery_beat/models.py:265 182 | msgid "solar" 183 | msgstr "" 184 | 185 | #: django_celery_beat/models.py:265 186 | msgid "Use a solar schedule" 187 | msgstr "使用solar调度" 188 | 189 | #: django_celery_beat/models.py:268 190 | msgid "Arguments" 191 | msgstr "元组参数" 192 | 193 | #: django_celery_beat/models.py:269 194 | msgid "JSON encoded positional arguments" 195 | msgstr "JSON编码的元组参数" 196 | 197 | #: django_celery_beat/models.py:272 198 | msgid "Keyword arguments" 199 | msgstr "字典参数" 200 | 201 | #: django_celery_beat/models.py:273 202 | msgid "JSON encoded keyword arguments" 203 | msgstr "JSON编码的字典参数" 204 | 205 | #: django_celery_beat/models.py:276 206 | msgid "queue" 207 | msgstr "队列" 208 | 209 | #: django_celery_beat/models.py:277 210 | msgid "Queue defined in CELERY_TASK_QUEUES" 211 | msgstr "在CELERY_TASK_QUEUES中定义的队列" 212 | 213 | #: django_celery_beat/models.py:280 214 | msgid "exchange" 215 | msgstr "交换机" 216 | 217 | #: django_celery_beat/models.py:283 218 | msgid "routing key" 219 | msgstr "路由KEY" 220 | 221 | #: django_celery_beat/models.py:286 222 | msgid "priority" 223 | msgstr "" 224 | 225 | #: django_celery_beat/models.py:290 226 | msgid "expires" 227 | msgstr "过期时间" 228 | 229 | #: django_celery_beat/models.py:293 230 | msgid "one-off task" 231 | msgstr "" 232 | 233 | #: django_celery_beat/models.py:296 234 | msgid "start_time" 235 | msgstr "开始时间" 236 | 237 | #: django_celery_beat/models.py:299 238 | msgid "enabled" 239 | msgstr "启用" 240 | 241 | #: django_celery_beat/models.py:309 242 | msgid "description" 243 | msgstr "任务描述" 244 | 245 | #: django_celery_beat/models.py:317 246 | msgid "periodic task" 247 | msgstr "定时任务" 248 | 249 | #: django_celery_beat/models.py:318 250 | msgid "periodic tasks" 251 | msgstr "定时任务配置" 252 | -------------------------------------------------------------------------------- /third_party_app_trans/django_celery_beat/locale/zh/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuyue92tree/rest_backend/95043681defaa96ea8ec9aea17d729a4282fd68e/third_party_app_trans/django_celery_beat/locale/zh/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /third_party_app_trans/django_celery_beat/locale/zh/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2019-03-12 11:38+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: django_celery_beat/admin.py:71 21 | msgid "Task (registered)" 22 | msgstr "任务(已注册)" 23 | 24 | #: django_celery_beat/admin.py:75 25 | msgid "Task (custom)" 26 | msgstr "任务(自定义)" 27 | 28 | #: django_celery_beat/admin.py:92 29 | msgid "Need name of task" 30 | msgstr "" 31 | 32 | #: django_celery_beat/admin.py:103 33 | #, python-format 34 | msgid "Unable to parse JSON: %s" 35 | msgstr "无法解析的JSON串: %s" 36 | 37 | #: django_celery_beat/admin.py:162 38 | #, python-brace-format 39 | msgid "{0} task{1} {2} successfully {3}" 40 | msgstr "{0} 任务{1} {2} 成功 {3}" 41 | 42 | #: django_celery_beat/admin.py:165 django_celery_beat/admin.py:208 43 | msgid "was,were" 44 | msgstr "" 45 | 46 | #: django_celery_beat/admin.py:174 47 | msgid "Enable selected tasks" 48 | msgstr "启用已选中的任务" 49 | 50 | #: django_celery_beat/admin.py:180 51 | msgid "Disable selected tasks" 52 | msgstr "禁用已选中的任务" 53 | 54 | #: django_celery_beat/admin.py:192 55 | msgid "Toggle activity of selected tasks" 56 | msgstr "" 57 | 58 | #: django_celery_beat/admin.py:205 59 | #, python-brace-format 60 | msgid "{0} task{1} {2} successfully run" 61 | msgstr "{0} 任务{1} {2} 启动成功" 62 | 63 | #: django_celery_beat/admin.py:211 64 | msgid "Run selected tasks" 65 | msgstr "执行已选中的任务" 66 | 67 | #: django_celery_beat/apps.py:15 68 | msgid "Periodic Tasks" 69 | msgstr "任务调度系统" 70 | 71 | #: django_celery_beat/models.py:27 72 | msgid "Days" 73 | msgstr "日" 74 | 75 | #: django_celery_beat/models.py:28 76 | msgid "Hours" 77 | msgstr "时" 78 | 79 | #: django_celery_beat/models.py:29 80 | msgid "Minutes" 81 | msgstr "分" 82 | 83 | #: django_celery_beat/models.py:30 84 | msgid "Seconds" 85 | msgstr "秒" 86 | 87 | #: django_celery_beat/models.py:31 88 | msgid "Microseconds" 89 | msgstr "毫秒" 90 | 91 | #: django_celery_beat/models.py:47 92 | msgid "event" 93 | msgstr "" 94 | 95 | #: django_celery_beat/models.py:50 96 | msgid "latitude" 97 | msgstr "" 98 | 99 | #: django_celery_beat/models.py:53 100 | msgid "longitude" 101 | msgstr "" 102 | 103 | #: django_celery_beat/models.py:59 104 | msgid "solar event" 105 | msgstr "solar" 106 | 107 | #: django_celery_beat/models.py:60 108 | msgid "solar events" 109 | msgstr "Solar配置" 110 | 111 | #: django_celery_beat/models.py:104 112 | msgid "every" 113 | msgstr "每" 114 | 115 | #: django_celery_beat/models.py:106 116 | msgid "period" 117 | msgstr "日期单位" 118 | 119 | #: django_celery_beat/models.py:112 django_celery_beat/models.py:257 120 | msgid "interval" 121 | msgstr "时间区间" 122 | 123 | #: django_celery_beat/models.py:113 124 | msgid "intervals" 125 | msgstr "时间区间配置" 126 | 127 | #: django_celery_beat/models.py:136 128 | #, python-brace-format 129 | msgid "every {0.period_singular}" 130 | msgstr "" 131 | 132 | #: django_celery_beat/models.py:137 133 | #, python-brace-format 134 | msgid "every {0.every} {0.period}" 135 | msgstr "" 136 | 137 | #: django_celery_beat/models.py:156 138 | msgid "minute" 139 | msgstr "" 140 | 141 | #: django_celery_beat/models.py:160 142 | msgid "hour" 143 | msgstr "" 144 | 145 | #: django_celery_beat/models.py:164 146 | msgid "day of week" 147 | msgstr "" 148 | 149 | #: django_celery_beat/models.py:168 150 | msgid "day of month" 151 | msgstr "" 152 | 153 | #: django_celery_beat/models.py:172 154 | msgid "month of year" 155 | msgstr "" 156 | 157 | #: django_celery_beat/models.py:181 django_celery_beat/models.py:261 158 | msgid "crontab" 159 | msgstr "" 160 | 161 | #: django_celery_beat/models.py:182 162 | msgid "crontabs" 163 | msgstr "Crontab配置" 164 | 165 | #: django_celery_beat/models.py:251 166 | msgid "name" 167 | msgstr "" 168 | 169 | #: django_celery_beat/models.py:252 170 | msgid "Useful description" 171 | msgstr "有益的描述" 172 | 173 | #: django_celery_beat/models.py:254 174 | msgid "task name" 175 | msgstr "任务名称" 176 | 177 | #: django_celery_beat/models.py:261 178 | msgid "Use one of interval/crontab" 179 | msgstr "使用interval/crontab中的一个" 180 | 181 | #: django_celery_beat/models.py:265 182 | msgid "solar" 183 | msgstr "" 184 | 185 | #: django_celery_beat/models.py:265 186 | msgid "Use a solar schedule" 187 | msgstr "使用solar调度" 188 | 189 | #: django_celery_beat/models.py:268 190 | msgid "Arguments" 191 | msgstr "元组参数" 192 | 193 | #: django_celery_beat/models.py:269 194 | msgid "JSON encoded positional arguments" 195 | msgstr "JSON编码的元组参数" 196 | 197 | #: django_celery_beat/models.py:272 198 | msgid "Keyword arguments" 199 | msgstr "字典参数" 200 | 201 | #: django_celery_beat/models.py:273 202 | msgid "JSON encoded keyword arguments" 203 | msgstr "JSON编码的字典参数" 204 | 205 | #: django_celery_beat/models.py:276 206 | msgid "queue" 207 | msgstr "队列" 208 | 209 | #: django_celery_beat/models.py:277 210 | msgid "Queue defined in CELERY_TASK_QUEUES" 211 | msgstr "在CELERY_TASK_QUEUES中定义的队列" 212 | 213 | #: django_celery_beat/models.py:280 214 | msgid "exchange" 215 | msgstr "交换机" 216 | 217 | #: django_celery_beat/models.py:283 218 | msgid "routing key" 219 | msgstr "路由KEY" 220 | 221 | #: django_celery_beat/models.py:286 222 | msgid "priority" 223 | msgstr "" 224 | 225 | #: django_celery_beat/models.py:290 226 | msgid "expires" 227 | msgstr "过期时间" 228 | 229 | #: django_celery_beat/models.py:293 230 | msgid "one-off task" 231 | msgstr "" 232 | 233 | #: django_celery_beat/models.py:296 234 | msgid "start_time" 235 | msgstr "开始时间" 236 | 237 | #: django_celery_beat/models.py:299 238 | msgid "enabled" 239 | msgstr "启用" 240 | 241 | #: django_celery_beat/models.py:309 242 | msgid "description" 243 | msgstr "任务描述" 244 | 245 | #: django_celery_beat/models.py:317 246 | msgid "periodic task" 247 | msgstr "定时任务" 248 | 249 | #: django_celery_beat/models.py:318 250 | msgid "periodic tasks" 251 | msgstr "定时任务配置" 252 | --------------------------------------------------------------------------------