LPOJ 开发教程(五)后端开发教程

LPOJ网址:www.lpoj.cn
LPOJ文档:docs.lpoj.cn

后端开发

后端的开发比前端的开发要简单很多,因为开发者只需专注于数据的呈现即可,不必关心显示的逻辑。在众多后端框架中,我选择了开发和学习成本较低的Python语言中的Django框架,同时Python语言与我们的判题程序又相辅相成,因此是一个很好的选择。Django是一个开源的Web框架,整体采用MVC的设计模式。但是在本系统中,我们并不需要构建自己的前端页面,我们只关心有哪些数据要交付给前端,因此本系统采用Django中的REST框架来快速构建自己的数据API。其中REST是RESTful的简称。RESTful是一种软件架构风格,它采用http协议,非常简单,任意客户端都能运行。因此我们只需要关心有哪些数据要交付给前端即可。其中REST框架主要分为三个部分,分别是Model,Serializer和View。Model即数据层,定义了数据在数据库中的形式。Serializer即序列化器,其中定义了各种数据库的操作,相当于一个中间层,最后View层决定了哪些数据可以呈现给用户,怎么呈现给用户等等。所以当开发者编写API时,只要着重于实现这三层即可。因为有了RESTful框架,这一切都变得非常简单便利。

Django REST framework 介绍

现在越来越多的网站采用前后端分离技术。在前后端分离的应用模式中,后端仅返回前端所需要的数据,不再渲染HTML页面,不再控制前端的效果。前端用户想要看到什么效果,从后端请求的数据如何加载到前端中,都由前端浏览器自己决定。在前后端分离的应用模式中,前端与后端的耦合度相对较低,我们通常将后端开发的每一视图都成为一个接口,或者API,前端通过访问接口来对数据进行增删改查。因此我们采用它进行我们的后端开发,同时他配套有各种各样的服务,如权限管理,路由管理,限流等等,这些在我们的判题系统中尤为重要。

因此本系统采用Django REST framework 开发,接下来跟着我的步伐,一步一步了解Django是如何在LPOJ中运作的!

安装Python3.7

整个开发在Ubuntu 18.10环境下进行,接下来所有教程均在此环境下进行,如果是Windows,请自行查阅安装方法。

Ubuntu自带Python3.6,经测试3.6一样适合本环境。但是Ubuntu中,Python命令默认是Python2,所以我们可以通过如下命令改变默认值,当然你也可以不改变,然后每次执行Python命令时使用的命令应该是Python3

sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 100
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 150

如果要还原到Python2,执行:

sudo update-alternatives --config python

接下来我们安装 pip ,pip是Python的一个包管理工具,可以使你很方便的下载Python的一些包,我们通过如下命令即可安装

sudo apt install python3-pip

安装必要环境

如若你要二次开发本OJ,首先要配置环境。

本后端主要用了如下几个库

  1. Django==2.2.1
  2. djangorestframework==3.9.3
  3. django-filter==2.1.0
  4. django-cors-headers==2.5.3
  5. mysqlclient==1.4.2.post1

其中第一个是整个Django框架所需的库,第二个是我们的REST Framework,第三个是用于实现过滤功能的一个框架,第四个是用于实现跨域访问的框架,第五个是访问Mysql所需要的库。

我们进入到Backend目录并执行如下命令即可。

pip3 install -r requirements.txt

如果在安装过程中出现错误,请自行百度错误信息并解决。
如果安装mysqlclient出现 /bin/sh: 1: mysql_config: not found错误,请执行如下语句:

sudo apt-get install libmysqlclient-dev

如无意外,应该会安装成功!

安装Mysql

其他操作请自行百度。

sudo apt-get install mysql-server

安装成功后我们新建一下数据库和修改一些配置。我们登录到数据库中然后执行如下语句。

mysql -uroot -p
mysql > CREATE DATABASE LPOJ DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql > USE mysql
mysql > GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'  IDENTIFIED BY 'your_password'  WITH GRANT OPTION;
mysql > ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password by 'your_password';
mysql > flush privileges;
mysql > exit;
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf 

具体内容的意思就是新建一个名为LPOJ的数据库,并给予root用户所有权限。

编辑setting.py

接下来我们修改一下配置文件,我们进入到Backend/Backend目录下,并修改setting.py文件

cd Backend
cd Backend
nano setting.py

我们主要修改数据库的配置信息,我们找到如下语句并修改else后面的内容为你的数据库信息。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'LPOJ',
        'USER': os.environ.get("DB_USER")  if os.environ.get("DB_USER") else 'root' , # 修改root为你的数据库用户
        'PASSWORD':os.environ.get("DB_PASSWORD")  if os.environ.get("DB_PASSWORD") else 'lpojdatabase', # 修改lpojdatabase为你的数据库密码
        'HOST': os.environ.get("DB_HOST")  if os.environ.get("DB_HOST") else 'lpojdatabase',# 修改lpojdatabase为你的数据库IP地址,如localhost
        'PORT': os.environ.get("DB_PORT")  if os.environ.get("DB_PORT") else 3306,
    }
}

运行后端

在Backend根目录中的manager.py是Django非常重要的一个文件,通过它我们可以实现很多操作,比较常用的操作如下:

makemigrations 将你编写的代码变成sql语句
migrate 将你编写的sql语句同步到数据库中
runserver 运行你的后端

首先将LPOJ的后端代码生成mysql语句,然后我们再同步到数据库中

python manager.py makemigrations
python manager.py migrate

执行完毕后查看数据库,会发现你的LPOJ数据库中多了若干表格,这些都是Django运行所需要的表格。

在运行之前让我们先制作一个超级用户,这在部署文档里面有写

echo "from django.contrib.auth.models import User; User.objects.filter(email=\"[email protected]\").delete(); User.objects.create_superuser(\"admin\", \"[email protected]\", \"admin\")" | python manage.py shell

最后我们再执行运行语句,以后如果对后端有任何修改,只需先执行

python manager.py makemigrations
python manager.py migrate

将修改同步到数据库中,然后再通过如下命令运行

python manage.py runserver 0.0.0.0:8000

意思是将后端暴露到8000端口中,并监听所有地址的访问。

接下来,我们就可以通过在浏览器中通过localhost:8000访问你的后端了。

如果能访问,证明你的后端已部署成功!

模块说明与开发

在阅读如下教程时,请先自行学习Django REST Framework的一些基本教程

接下在会对一些模块做简单介绍

  1. Backend 保存整个后台的配置文件和路由
  2. blog 博客模块
  3. board 排行榜相关模块
  4. contest 比赛相关模块
  5. judgestatus 提交信息模块
  6. problem 题目模块
  7. user 用户相关模块
  8. wiki Wiki模块
  9. ProblemData 存放题目数据的文件夹

本教程不会对每个模块都做详细介绍,但是会列出各文件的功能,和点出一些自己的实现方法。

Backend

setting.py

此处添加你自己的模块

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'django_filters',
    'judgestatus',
    'corsheaders',
    'problem',
    'user',
    'contest',
    'board',
    'blog',
    'wiki'
]

此处填写一下你使用的框架的设置,比如限流设置就是在此处实现。

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '300/m',
        'judge': '300/m',
        'post': '2000/m',
    }

}

此处是一下数据库的设置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'LPOJ',
        'USER': os.environ.get("DB_USER")  if os.environ.get("DB_USER") else 'root' ,
        'PASSWORD':os.environ.get("DB_PASSWORD")  if os.environ.get("DB_PASSWORD") else 'lpojdatabase',
        'HOST': os.environ.get("DB_HOST")  if os.environ.get("DB_HOST") else 'lpojdatabase',
        'PORT': os.environ.get("DB_PORT")  if os.environ.get("DB_PORT") else 3306,
    }
}

此处是跨域访问的设置

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

此处是Session过期设置

SESSION_COOKIE_AGE = 60 * 60 * 24  # 30分钟
SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True

urls.py

这个文件主要是用来填写路由信息

修改后端

已存在的接口可以根据需要修改,这里将以添加一个模块为例,展示如何添加一个自己的后台模块或者在已有模块中添加一个API

在已有模块中添加一个API

现在我们假定要在Blog模块中添加一个博客回复功能

  1. 添加你的model

修改models.py文件,在文件最后添加

class BlogComment(models.Model):
    # 此处编写你的字段
    username = models.CharField(max_length=50)
    msg = models.CharField(max_length=1000)
    time = models.DateField(auto_now=True)

    # 复制粘贴即可
    objects = models.Manager()
  1. 添加你的序列化器

修改serializers.py文件来

from .models import BlogComment # 记得import
class BlogCommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = BlogComment # 设置为你的model
        fields = '__all__'

具体的修改参考Django教程,这里使用REST Framework模块,使得这一切都如此简单

  1. 添加视图类

修改views.py来添加

from .models import BlogComment
from .serializers import BlogCommentSerializer
class BlogCommentView(viewsets.ModelViewSet): # 得益于rest_framework,构建一个视图变得很方便
    queryset = BlogComment.objects.all() # 查询集合,具体功能和修改,参考Django文档
    serializer_class = BlogCommentSerializer # 你的序列化器
    filter_fields = ('username', 'time') # 过滤字段,使得你可以在http请求中过滤,如 /?username=123456
    pagination_class = LimitOffsetPagination # 分页器,使得你的http请求支持分页,具体自行百度
    permission_classes = (ManagerOnly,) # 权限过滤器,具体参考Django文档

    throttle_scope = "post" # 限流类,直接复制粘贴即可
    throttle_classes = [ScopedRateThrottle, ]
  1. 添加路由信息

我们修改urls.py文件在 urlpatterns = [url(’’, include(routers.urls)),] 上方添加

routers.register('blogcomment', views.BlogCommentView) # 第一个参数为你的路由,第二个参数为你的视图

至此,我们成功的添加了一个自己的API

现在只需要同步你的数据库

python manager.py makemigrations blog
python manager.py migrate blog

现在可以通过 http://localhost:8000/blogcomment/
来访问你的API了

我们可以通过POST请求来添加一个数据,用PUT请求来修改一个数据
用DELETE请求来删除一个数据,用GET请求来获取所有数据

具体自行阅读HTTP请求的相关教程。

我们可以通过primary_key来获取单个数据,如

http://localhost:8000/blogcomment/1/

Django会默认的生成一个ID字段作为primary_key,当然你也可以自己制定,具体自行参阅Django教程。

我们可以通过limit和offset来实现分页,如

http://localhost:8000/blogcomment/?limit=50&offset=10

我们可以直接过滤设定好的字段,如

http://localhost:8000/blogcomment/?username=123&time=2019-5-29

这样一个普通的API很不安全,因此要做权限认证,自行编辑一个权限类,然后添加到permission_classes中,具体代码编写自行参考Django教程

新建一个模块

我们可以直接新建一个模块,这非常简单,首先我们先执行如下命令

python manage.py startapp yourappname

这样就成功新建一个模块了,我们查看目录会发现多了一个yourappname的文件夹

然后我们要注册我们的模块,我们先修改Backend/Backend/setting.py文件

INSTALLED_APPS中添加你的模块名字

然后我们就可以参阅上面的在已有模块中添加一个API的教程来添加你的API

如果文件不存在,自行新建对应的文件在目录里即可,具体的内容也可以参考现有的模块。

我们添加完毕后要在Backend中注册你的路由信息。

我们修改Backend/Backend/urls.pyurlpatterns中添加

url(r’’, include(‘yourappname.urls’))

这样就可以了。

不要忘了同步你的数据库

python manager.py makemigrations yourappname
python manager.py migrate yourappname

以上就是后端开发教程,接下来会介绍LPOJ中各个模块的功能

发布了401 篇原创文章 · 获赞 61 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/lzc504603913/article/details/90676366