增加部分django和celery设置,同时实验获取题目详情

This commit is contained in:
virusdefender 2016-03-09 15:55:21 +08:00
parent 44749dd94c
commit 960d060109
11 changed files with 193 additions and 29 deletions

View File

@ -0,0 +1,3 @@
# coding=utf-8
from __future__ import absolute_import
from .celery import app as celery_app

19
openvj/celery.py Normal file
View File

@ -0,0 +1,19 @@
# coding=utf-8
from __future__ import absolute_import
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openvj.settings')
from django.conf import settings
app = Celery('openvj')
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
# load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

View File

@ -18,4 +18,19 @@ DATABASES = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
}
REDIS = {
"HOST": "127.0.0.1",
"PORT": 6379,
"PASSWORD": "123456"
}
# celery配置
BROKER_URL = "redis://{host}:{port}/{db}".format(host=REDIS["HOST"], port=REDIS["PORT"], db=0)
CELERY_RESULT_BACKEND = "redis"
CELERY_REDIS_HOST = REDIS["HOST"]
CELERY_REDIS_PORT = REDIS["PORT"]
CELERY_REDIS_DB = 0

View File

@ -18,4 +18,6 @@ DATABASES = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
}
BROKER_URL = 'amqp://guest:guest@localhost//'

View File

@ -44,7 +44,9 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'server',
]
MIDDLEWARE_CLASSES = [
@ -103,7 +105,7 @@ AUTH_PASSWORD_VALIDATORS = [
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
@ -115,4 +117,4 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_URL = '/static/'
STATIC_URL = '/static/'

View File

@ -16,6 +16,9 @@ Including another URLconf
from django.conf.urls import url
from django.contrib import admin
from server.views import ProblemAPIView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^problem/$', ProblemAPIView.as_view()),
]

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-03-08 08:20
# Generated by Django 1.9.4 on 2016-03-09 06:08
from __future__ import unicode_literals
from django.db import migrations, models
@ -32,6 +32,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30)),
('robot', models.CharField(max_length=50)),
('is_valid', models.BooleanField(default=True)),
],
options={
@ -43,18 +44,18 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('url', models.URLField()),
('submit_url', models.URLField()),
('title', models.CharField(max_length=100)),
('description', models.TextField()),
('time_limit', models.IntegerField()),
('memory_limit', models.IntegerField()),
('input_description', models.TextField()),
('output_description', models.TextField()),
('samples', models.TextField()),
('spj', models.BooleanField()),
('hint', models.TextField()),
('submit_url', models.URLField(blank=True, null=True)),
('title', models.CharField(blank=True, max_length=100, null=True)),
('description', models.TextField(blank=True, null=True)),
('time_limit', models.IntegerField(blank=True, null=True)),
('memory_limit', models.IntegerField(blank=True, null=True)),
('input_description', models.TextField(blank=True, null=True)),
('output_description', models.TextField(blank=True, null=True)),
('samples', models.TextField(blank=True, null=True)),
('spj', models.BooleanField(default=False)),
('hint', models.TextField(blank=True, null=True)),
('is_valid', models.BooleanField(default=True)),
('status', models.IntegerField()),
('status', models.IntegerField(choices=[(0, 'Done'), (1, 'Crawling'), (2, 'Failed')])),
('task_id', models.CharField(max_length=40)),
('oj', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='server.OJ')),
],
@ -62,6 +63,12 @@ class Migration(migrations.Migration):
'db_table': 'problem',
},
),
migrations.CreateModel(
name='ProblemStatus',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
migrations.CreateModel(
name='RobotStatusInfo',
fields=[
@ -81,7 +88,7 @@ class Migration(migrations.Migration):
('password', models.CharField(max_length=30)),
('is_valid', models.BooleanField(default=True)),
('last_login_time', models.DateTimeField()),
('status', models.IntegerField(choices=[('Occupied', 1), ('free', 0)])),
('status', models.IntegerField(choices=[(1, 'Occupied'), (0, 'Free')])),
('oj', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='server.OJ')),
],
options={

View File

@ -6,11 +6,15 @@ from django.db import models
class OJ(models.Model):
name = models.CharField(max_length=30)
robot = models.CharField(max_length=50)
is_valid = models.BooleanField(default=True)
class Meta:
db_table = "oj"
def __str__(self):
return self.name
class APIKey(models.Model):
api_key = models.CharField(max_length=40)
@ -21,6 +25,9 @@ class APIKey(models.Model):
class Meta:
db_table = "api_key"
def __str__(self):
return self.name
class RobotUserStatus(object):
occupied = 1
@ -39,6 +46,9 @@ class RobotUser(models.Model):
db_table = "robot_user"
unique_together = (("oj", "username"), )
def __str__(self):
return self.oj.name + " - " + self.username
class RobotStatusInfo(models.Model):
status_info = models.TextField()
@ -48,6 +58,9 @@ class RobotStatusInfo(models.Model):
class Meta:
db_table = "robot_status_info"
def __str__(self):
return self.robot_user.username + self.status_info
class ProblemStatus(models.Model):
done = 0
@ -58,16 +71,16 @@ class ProblemStatus(models.Model):
class Problem(models.Model):
oj = models.ForeignKey(OJ)
url = models.URLField()
submit_url = models.URLField()
title = models.CharField(max_length=100)
description = models.TextField()
time_limit = models.IntegerField()
memory_limit = models.IntegerField()
input_description = models.TextField()
output_description = models.TextField()
samples = models.TextField()
spj = models.BooleanField()
hint = models.TextField()
submit_url = models.URLField(blank=True, null=True)
title = models.CharField(max_length=100, blank=True, null=True)
description = models.TextField(blank=True, null=True)
time_limit = models.IntegerField(blank=True, null=True)
memory_limit = models.IntegerField(blank=True, null=True)
input_description = models.TextField(blank=True, null=True)
output_description = models.TextField(blank=True, null=True)
samples = models.TextField(blank=True, null=True)
spj = models.BooleanField(default=False)
hint = models.TextField(blank=True, null=True)
is_valid = models.BooleanField(default=True)
status = models.IntegerField(choices=((ProblemStatus.done, "Done"),
(ProblemStatus.crawling, "Crawling"),
@ -77,6 +90,12 @@ class Problem(models.Model):
class Meta:
db_table = "problem"
def __str__(self):
if not self.title:
return self.oj.name + " Problem Status: " + str(self.status)
else:
return self.oj.name + " - " + self.title
class Submission(models.Model):
problem = models.ForeignKey(Problem)

9
server/serializers.py Normal file
View File

@ -0,0 +1,9 @@
# coding=utf-8
from rest_framework import serializers
from .models import Problem
class ProblemSerializer(serializers.ModelSerializer):
class Meta:
model = Problem

8
server/tasks.py Normal file
View File

@ -0,0 +1,8 @@
# coding=utf-8
from __future__ import absolute_import
from celery import shared_task
@shared_task
def get_problem(robot, url):
return robot.get_problem(url)

View File

@ -1,3 +1,80 @@
from django.shortcuts import render
# coding=utf-8
import json
from rest_framework.views import APIView
from rest_framework.response import Response
from celery import states
from .serializers import ProblemSerializer
from .models import OJ, Problem, RobotUser, RobotStatusInfo, ProblemStatus
from .tasks import get_problem
def error_response(error_reason):
return Response(data={"code": 1, "data": error_reason})
def serializer_invalid_response(serializer):
for k, v in serializer.errors.iteritems():
return error_response(k + " : " + v[0])
def success_response(data):
return Response(data={"code": 0, "data": data})
def import_class(cl):
d = cl.rfind(".")
class_name = cl[d+1:len(cl)]
m = __import__(cl[0:d], globals(), locals(), [class_name])
return getattr(m, class_name)
class ProblemAPIView(APIView):
def get(self, request):
oj = request.GET.get("oj")
url = request.GET.get("url")
if not (oj and url):
return error_response("参数错误")
try:
problem = Problem.objects.get(url=url, is_valid=True)
if problem.status == ProblemStatus.done:
return success_response(ProblemSerializer(problem).data)
elif problem.status == ProblemStatus.crawling:
task = get_problem.AsyncResult(problem.task_id)
if task.state == states.SUCCESS:
result = task.get()
problem.title = result["title"]
problem.submit_url = result["submit_url"]
problem.description = result["description"]
problem.time_limit = result["time_limit"]
problem.memory_limit = result["memory_limit"]
problem.input_description = result["input_description"]
problem.output_description = result["output_description"]
problem.samples = json.dumps(result["samples"])
problem.status = ProblemStatus.done
problem.save()
return success_response(ProblemSerializer(problem).data)
elif task.state == states.FAILURE:
problem.status = ProblemStatus.failed
problem.save()
return success_response({"status": ProblemStatus.failed})
elif problem.status == ProblemStatus.failed:
return success_response({"status": ProblemStatus.failed})
except Problem.DoesNotExist:
pass
try:
oj = OJ.objects.get(name=oj, is_valid=True)
except OJ.DoesNotExist:
return error_response("不存在该oj")
robot_status = RobotStatusInfo.objects.filter(robot_user__oj=oj).first()
if not robot_status:
return error_response("登录信息错误")
robot = import_class(oj.robot)(**json.loads(robot_status.status_info))
if not robot.check_url(url):
return error_response("url格式错误")
task_id = get_problem.delay(robot, url).id
Problem.objects.create(oj=oj, url=url, status=ProblemStatus.crawling, task_id=task_id)
return success_response({"status": ProblemStatus.crawling})
# Create your views here.