robot attachment viewer backend
pip3 install -r ./requirement.txtpython3 manage.py runserver --settings=robot_view.dev_settingsor
./dev_robot.shPlease install the docker-compose before you use it.
docker-compose build && docker-compose upthen visit the localhost:8000
use docker can make deploy more easy than before, and use the same system env can solve the cross-platform problems
- create the Dockerfile file
- Install the
docker-composecommand tools and create the docker-compose.yml file - run
docker-compose buildto build the web image and database image, usedocker-compose runto run these containers
- login travis-ci and add the current repos on github
- create the
.travis.ymlin project - add the ssh key by this command, in order to deploy the code to server
travis encrypt-file ~/.ssh/id_rsa --addbecause I prefer using mysql database in the dev env, and use postgres in production env in docker container, so split the settings is very important. there are many blog can search form google, just use the simplest method.
- create the
dev_settings.py - import all item in
settings.py - overwrite the item what you want to change.
- run commands in
manage.pywith--settings=robot_view.dev_settingsor other settings file, default setting file issettings.pyinrobot_view
if app has very huge number, leave them in the project root path is not a smart choice, so create the apps path to store them
- modify the
settings.py, to configure the apps as resource path
import os
import sys
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))- if use pycharm, also can mark the
appspath asSource Root, trust me, It's a smart action.
pip3 install -r /code/robot/requirements.txt -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.comif use docker, modify the Dockerfile
- RUN pip3 install -r /code/robot/requirements.txt
+ RUN pip3 install -r /code/robot/requirements.txt -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.combecause Django will handle the request for the static file only when the DEBUG option in settings is True, if run in production env, developer must handle it by himself.
- declare the
STATIC_ROOTinsettings.py, or your custom setting files - install
whitenoisevia pip and edit thewsgi.pyinrobot_view
pip install whitenoise
# export the dependencies in requirements.txt
pip freeze > ./requirements.txtfrom whitenoise.django import DjangoWhiteNoise
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
application = DjangoWhiteNoise(application)- then run this command:
# collect the static file from the package like rest-framework
# to the STATIC_ROOT path where declare in settings file
python manage.py collectstatic- then rebuild the docker image and run it
# -d option can make the process in daemon mode.
docker-compose build && docker-compose up -ddjango rest framework already support the docs and schema itself, just include it and add a urlpatterns is enough:
from rest_framework.schemas import get_schema_view
from django.urls import path, include
from rest_framework.documentation import include_docs_urls
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
schema_view = get_schema_view(title="Server Monitoring API")
urlpatterns = [
path('', include(router.urls)),
path('schema/', schema_view),
path('docs/', include_docs_urls(title='doc', description='desc'))
]After configure the router for user app, in development env, app can work very will, when build docker container, app throw a error: list object is not callable
Solution is very easy: use the tuple, don't use list.
# robot_view/setting.py
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
'PAGE_SIZE': 10,
'DEFAULT_PAGINATION_CLASS': (
'rest_framework.pagination.PageNumberPagination'
)
}-
edit setting.py, and the
AUTHENTICATION_BACKENDSAUTHENTICATION_BACKENDS = ( 'users.views.CustomBackend', 'django.contrib.auth.backends.ModelBackend' )
-
post the
usernameandpasswordto http://127.0.0.1:8001/login/ to exchange the jwt -
and
Authorizationrequest header andBearerprefix for jwt string
for rpc, I choose to use apache thrift framework
-
install
django-thrift:pip install django-thrift
-
configure
django-thriftin setting.py- add
'django_thrift'inINSTALLED_APPS - add
THRIFTconfigure option in setting.py - add
FILEoption inTHRIFTpoint to*.thriftfile - add
SERVICEoption named is the same to thethriftserver name
- add
-
write the thrift handler in django app
view:# import the create_handler from django_thrift.handler import create_handler # get a handler instantiation handler = create_handler() # defined the thrift method @handler.map_function("saveRobotData") def save_robot_data_handler(): return {"a": "bb"} # more thrift methods can be defined
-
management thrift server on localhost 9090
# start rpc server python manage.py runrpcserver
Because I need change the thrift server listen host and port, but django-thrift library can't support change these in setting.py, so I have to modify the source code of this library.
-
create
extra_appfoldermkdir extra_app
-
move the
django-thriftlibrary fromsite-packagetoextra-app:mv to_your_site_package_path/django-thrift extra_app
-
add
extra-appinPYTHONPATHvia modify the setting.pyimport sys, os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
-
modify the
django-thriftsource code what you want to edit.
before I do these, only the user which create via django manage.py command createsuperuser can generate current JSON WEB Token. So I want to know why.
the user Profile data store in users_userporfile table, the password field which user is created by command is encrypted, so I need use the same methods to encrypt the password before save it in database.
search in django source code, I find the make_password function, and when use create superuser, the manage.py don't provide the salt, so just use the like base_user.py:
from django.contrib.auth.hashers import make_password
def validate(self, attrs):
# because the limit from serializer, add 'raw_password' prop is forbidden.
# attrs["raw_password"] = attrs["password"]
attrs["password"] = make_password(attrs["password"])
return attrsthe minimum code implementation :
from django.db.models import Q
from django.contrib.auth import get_user_model
from rest_framework import viewsets, status, response
from rest_framework.mixins import RetrieveModelMixin
User = get_user_model()
class ExampleViewSet(RetrieveModelMixin, viewsets.GenericViewSet):
def retrieve(self, request, *args, **kwargs):
queryset = self.get_object()
serializer = self.get_serializer(queryset)
re_dict = serializer.data
re_dict["username"] = User.objects.get(Q(id=re_dict["user"])).username
del re_dict["user"]
headers = self.get_success_headers(serializer.data)
return response.Response(re_dict, status=status.HTTP_200_OK, headers=headers)| List Length | time |
|---|---|
| 100 | 2s |
| 100,000 | 206s |
server {
listen 80;
server_name robot.raoul1996.cn;
root /usr/share/nginx/html/robot;
location / {
}
location ~* ^/api|static/ {
rewrite ^/api/(.*) /$1 break;
proxy_pass http://your_ip:your_port;
}
}