mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-01-17 01:54:52 +00:00
Merge branch 'zemal_dev'
This commit is contained in:
commit
df0b0c1108
2
.gitignore
vendored
2
.gitignore
vendored
@ -53,6 +53,7 @@ db.db
|
|||||||
*.rdb
|
*.rdb
|
||||||
#*.out
|
#*.out
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
|
.python-version
|
||||||
.DS_Store
|
.DS_Store
|
||||||
build.txt
|
build.txt
|
||||||
tmp/
|
tmp/
|
||||||
@ -69,3 +70,4 @@ data/public/upload/*
|
|||||||
!data/public/upload/.gitkeep
|
!data/public/upload/.gitkeep
|
||||||
data/public/avatar/*
|
data/public/avatar/*
|
||||||
!data/public/avatar/default.png
|
!data/public/avatar/default.png
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
3.6.2
|
|
@ -5,6 +5,8 @@ ENV OJ_ENV production
|
|||||||
ADD . /app
|
ADD . /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=5s --retries=3 CMD python2 /app/deploy/health_check.py
|
||||||
|
|
||||||
RUN printf "https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.6/community/\nhttps://mirrors.tuna.tsinghua.edu.cn/alpine/v3.6/main/" > /etc/apk/repositories && \
|
RUN printf "https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.6/community/\nhttps://mirrors.tuna.tsinghua.edu.cn/alpine/v3.6/main/" > /etc/apk/repositories && \
|
||||||
apk add --update --no-cache build-base nginx openssl curl unzip supervisor jpeg-dev zlib-dev postgresql-dev freetype-dev && \
|
apk add --update --no-cache build-base nginx openssl curl unzip supervisor jpeg-dev zlib-dev postgresql-dev freetype-dev && \
|
||||||
pip install --no-cache-dir -r /app/deploy/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple && \
|
pip install --no-cache-dir -r /app/deploy/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple && \
|
||||||
@ -12,4 +14,5 @@ RUN printf "https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.6/community/\nhttps:/
|
|||||||
RUN curl -L $(curl -s https://api.github.com/repos/QingdaoU/OnlineJudgeFE/releases/latest | grep /dist.zip | cut -d '"' -f 4) -o dist.zip && \
|
RUN curl -L $(curl -s https://api.github.com/repos/QingdaoU/OnlineJudgeFE/releases/latest | grep /dist.zip | cut -d '"' -f 4) -o dist.zip && \
|
||||||
unzip dist.zip && \
|
unzip dist.zip && \
|
||||||
rm dist.zip
|
rm dist.zip
|
||||||
|
|
||||||
CMD sh /app/deploy/run.sh
|
CMD sh /app/deploy/run.sh
|
||||||
|
11
README-CN.md
11
README-CN.md
@ -30,7 +30,11 @@
|
|||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
文档: [https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0](https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0)
|
请根据此进行安装: [https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0](https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0)
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
[http://docs.onlinejudge.me/](http://docs.onlinejudge.me/)
|
||||||
|
|
||||||
## 截图
|
## 截图
|
||||||
|
|
||||||
@ -64,6 +68,11 @@ Rankings 中可以控制图表和菜单的显隐。
|
|||||||
|
|
||||||
![create-contest](https://user-images.githubusercontent.com/20637881/33372514-428ab922-d539-11e7-8f68-da55dedf3ad3.png)
|
![create-contest](https://user-images.githubusercontent.com/20637881/33372514-428ab922-d539-11e7-8f68-da55dedf3ad3.png)
|
||||||
|
|
||||||
|
|
||||||
|
## 浏览器支持
|
||||||
|
|
||||||
|
Modern browsers(chrome, firefox) 和 Internet Explorer 10+.
|
||||||
|
|
||||||
## 特别感谢
|
## 特别感谢
|
||||||
|
|
||||||
+ 所有为本项目做出贡献的人
|
+ 所有为本项目做出贡献的人
|
||||||
|
@ -32,6 +32,10 @@ The main modules are open source:
|
|||||||
|
|
||||||
Follow me: [https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0](https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0)
|
Follow me: [https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0](https://github.com/QingdaoU/OnlineJudgeDeploy/tree/2.0)
|
||||||
|
|
||||||
|
## Documents
|
||||||
|
|
||||||
|
[http://docs.onlinejudge.me/](http://docs.onlinejudge.me/)
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
### Frontend:
|
### Frontend:
|
||||||
@ -64,6 +68,10 @@ You can control the menu and chart status in rankings.
|
|||||||
|
|
||||||
![create-contest](https://user-images.githubusercontent.com/20637881/33372514-428ab922-d539-11e7-8f68-da55dedf3ad3.png)
|
![create-contest](https://user-images.githubusercontent.com/20637881/33372514-428ab922-d539-11e7-8f68-da55dedf3ad3.png)
|
||||||
|
|
||||||
|
## Browser Support
|
||||||
|
|
||||||
|
Modern browsers(chrome, firefox) 和 Internet Explorer 10+.
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|
||||||
+ I'd appreciate a github star if you find this helpful
|
+ I'd appreciate a github star if you find this helpful
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from utils.api import DateTimeTZField, serializers, UsernameSerializer
|
from utils.api import serializers, UsernameSerializer
|
||||||
|
|
||||||
from .models import AdminType, ProblemPermission, User, UserProfile
|
from .models import AdminType, ProblemPermission, User, UserProfile
|
||||||
|
|
||||||
@ -50,8 +50,6 @@ class ImportUserSeralizer(serializers.Serializer):
|
|||||||
|
|
||||||
class UserAdminSerializer(serializers.ModelSerializer):
|
class UserAdminSerializer(serializers.ModelSerializer):
|
||||||
real_name = serializers.SerializerMethodField()
|
real_name = serializers.SerializerMethodField()
|
||||||
create_time = DateTimeTZField()
|
|
||||||
last_login = DateTimeTZField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
@ -63,9 +61,6 @@ class UserAdminSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.ModelSerializer):
|
class UserSerializer(serializers.ModelSerializer):
|
||||||
create_time = DateTimeTZField()
|
|
||||||
last_login = DateTimeTZField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ["id", "username", "email", "admin_type", "problem_permission",
|
fields = ["id", "username", "email", "admin_type", "problem_permission",
|
||||||
@ -74,22 +69,12 @@ class UserSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class UserProfileSerializer(serializers.ModelSerializer):
|
class UserProfileSerializer(serializers.ModelSerializer):
|
||||||
user = UserSerializer()
|
user = UserSerializer()
|
||||||
acm_problems_status = serializers.JSONField()
|
|
||||||
oi_problems_status = serializers.JSONField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserProfile
|
model = UserProfile
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class UserInfoSerializer(serializers.ModelSerializer):
|
|
||||||
acm_problems_status = serializers.JSONField()
|
|
||||||
oi_problems_status = serializers.JSONField()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = UserProfile
|
|
||||||
|
|
||||||
|
|
||||||
class EditUserSerializer(serializers.Serializer):
|
class EditUserSerializer(serializers.Serializer):
|
||||||
id = serializers.IntegerField()
|
id = serializers.IntegerField()
|
||||||
username = serializers.CharField(max_length=32)
|
username = serializers.CharField(max_length=32)
|
||||||
@ -105,12 +90,12 @@ class EditUserSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
class EditUserProfileSerializer(serializers.Serializer):
|
class EditUserProfileSerializer(serializers.Serializer):
|
||||||
real_name = serializers.CharField(max_length=32, allow_null=True, required=False)
|
real_name = serializers.CharField(max_length=32, allow_null=True, required=False)
|
||||||
avatar = serializers.CharField(max_length=256, allow_null=True, allow_blank=True, required=False)
|
avatar = serializers.CharField(max_length=256, allow_blank=True, required=False)
|
||||||
blog = serializers.URLField(max_length=256, allow_null=True, allow_blank=True, required=False)
|
blog = serializers.URLField(max_length=256, allow_blank=True, required=False)
|
||||||
mood = serializers.CharField(max_length=256, allow_null=True, allow_blank=True, required=False)
|
mood = serializers.CharField(max_length=256, allow_blank=True, required=False)
|
||||||
github = serializers.CharField(max_length=64, allow_null=True, allow_blank=True, required=False)
|
github = serializers.CharField(max_length=64, allow_blank=True, required=False)
|
||||||
school = serializers.CharField(max_length=64, allow_null=True, allow_blank=True, required=False)
|
school = serializers.CharField(max_length=64, allow_blank=True, required=False)
|
||||||
major = serializers.CharField(max_length=64, allow_null=True, allow_blank=True, required=False)
|
major = serializers.CharField(max_length=64, allow_blank=True, required=False)
|
||||||
|
|
||||||
|
|
||||||
class ApplyResetPasswordSerializer(serializers.Serializer):
|
class ApplyResetPasswordSerializer(serializers.Serializer):
|
||||||
@ -142,3 +127,4 @@ class RankInfoSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserProfile
|
model = UserProfile
|
||||||
|
fields = "__all__"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from utils.api import serializers
|
from utils.api import serializers
|
||||||
from utils.api._serializers import DateTimeTZField, UsernameSerializer
|
from utils.api._serializers import UsernameSerializer
|
||||||
|
|
||||||
from .models import Announcement
|
from .models import Announcement
|
||||||
|
|
||||||
@ -11,12 +11,11 @@ class CreateAnnouncementSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
|
|
||||||
class AnnouncementSerializer(serializers.ModelSerializer):
|
class AnnouncementSerializer(serializers.ModelSerializer):
|
||||||
create_time = DateTimeTZField()
|
|
||||||
last_update_time = DateTimeTZField()
|
|
||||||
created_by = UsernameSerializer()
|
created_by = UsernameSerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Announcement
|
model = Announcement
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class EditAnnouncementSerializer(serializers.Serializer):
|
class EditAnnouncementSerializer(serializers.Serializer):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from utils.api import DateTimeTZField, serializers
|
from utils.api import serializers
|
||||||
|
|
||||||
from .models import JudgeServer
|
from .models import JudgeServer
|
||||||
|
|
||||||
@ -29,8 +29,6 @@ class CreateEditWebsiteConfigSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
|
|
||||||
class JudgeServerSerializer(serializers.ModelSerializer):
|
class JudgeServerSerializer(serializers.ModelSerializer):
|
||||||
create_time = DateTimeTZField()
|
|
||||||
last_heartbeat = DateTimeTZField()
|
|
||||||
status = serializers.CharField()
|
status = serializers.CharField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from utils.api import DateTimeTZField, UsernameSerializer, serializers
|
from utils.api import UsernameSerializer, serializers
|
||||||
|
|
||||||
from .models import Contest, ContestAnnouncement, ContestRuleType
|
from .models import Contest, ContestAnnouncement, ContestRuleType
|
||||||
from .models import ACMContestRank, OIContestRank
|
from .models import ACMContestRank, OIContestRank
|
||||||
@ -29,16 +29,13 @@ class EditConetestSeriaizer(serializers.Serializer):
|
|||||||
|
|
||||||
|
|
||||||
class ContestAdminSerializer(serializers.ModelSerializer):
|
class ContestAdminSerializer(serializers.ModelSerializer):
|
||||||
start_time = DateTimeTZField()
|
|
||||||
end_time = DateTimeTZField()
|
|
||||||
create_time = DateTimeTZField()
|
|
||||||
last_update_time = DateTimeTZField()
|
|
||||||
created_by = UsernameSerializer()
|
created_by = UsernameSerializer()
|
||||||
status = serializers.CharField()
|
status = serializers.CharField()
|
||||||
contest_type = serializers.CharField()
|
contest_type = serializers.CharField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Contest
|
model = Contest
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class ContestSerializer(ContestAdminSerializer):
|
class ContestSerializer(ContestAdminSerializer):
|
||||||
@ -49,10 +46,10 @@ class ContestSerializer(ContestAdminSerializer):
|
|||||||
|
|
||||||
class ContestAnnouncementSerializer(serializers.ModelSerializer):
|
class ContestAnnouncementSerializer(serializers.ModelSerializer):
|
||||||
created_by = UsernameSerializer()
|
created_by = UsernameSerializer()
|
||||||
create_time = DateTimeTZField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ContestAnnouncement
|
model = ContestAnnouncement
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class CreateContestAnnouncementSerializer(serializers.Serializer):
|
class CreateContestAnnouncementSerializer(serializers.Serializer):
|
||||||
@ -76,10 +73,10 @@ class ContestPasswordVerifySerializer(serializers.Serializer):
|
|||||||
|
|
||||||
class ACMContestRankSerializer(serializers.ModelSerializer):
|
class ACMContestRankSerializer(serializers.ModelSerializer):
|
||||||
user = serializers.SerializerMethodField()
|
user = serializers.SerializerMethodField()
|
||||||
submission_info = serializers.JSONField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ACMContestRank
|
model = ACMContestRank
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.is_admin_role = kwargs.pop("is_admin_role", False)
|
self.is_admin_role = kwargs.pop("is_admin_role", False)
|
||||||
@ -91,10 +88,10 @@ class ACMContestRankSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class OIContestRankSerializer(serializers.ModelSerializer):
|
class OIContestRankSerializer(serializers.ModelSerializer):
|
||||||
user = serializers.SerializerMethodField()
|
user = serializers.SerializerMethodField()
|
||||||
submission_info = serializers.JSONField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = OIContestRank
|
model = OIContestRank
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.is_admin_role = kwargs.pop("is_admin_role", False)
|
self.is_admin_role = kwargs.pop("is_admin_role", False)
|
||||||
|
@ -3,7 +3,6 @@ from datetime import datetime, timedelta
|
|||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from utils.api._serializers import DateTimeTZField
|
|
||||||
from utils.api.tests import APITestCase
|
from utils.api.tests import APITestCase
|
||||||
|
|
||||||
from .models import ContestAnnouncement, ContestRuleType, Contest
|
from .models import ContestAnnouncement, ContestRuleType, Contest
|
||||||
@ -44,10 +43,9 @@ class ContestAdminAPITest(APITestCase):
|
|||||||
response = self.client.put(self.url, data=data)
|
response = self.client.put(self.url, data=data)
|
||||||
self.assertSuccess(response)
|
self.assertSuccess(response)
|
||||||
response_data = response.data["data"]
|
response_data = response.data["data"]
|
||||||
datetime_tz_field = DateTimeTZField()
|
|
||||||
for k in data.keys():
|
for k in data.keys():
|
||||||
if isinstance(data[k], datetime):
|
if isinstance(data[k], datetime):
|
||||||
data[k] = datetime_tz_field.to_representation(data[k])
|
continue
|
||||||
self.assertEqual(response_data[k], data[k])
|
self.assertEqual(response_data[k], data[k])
|
||||||
|
|
||||||
def test_get_contests(self):
|
def test_get_contests(self):
|
||||||
|
11
deploy/health_check.py
Normal file
11
deploy/health_check.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import xmlrpclib
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
server = xmlrpclib.Server('http://localhost:9005/RPC2')
|
||||||
|
info = server.supervisor.getAllProcessInfo()
|
||||||
|
error_states = list(filter(lambda x: x["state"] != 20, info))
|
||||||
|
exit(len(error_states))
|
||||||
|
except Exception as e:
|
||||||
|
print(e.with_traceback())
|
||||||
|
exit(1)
|
8
deploy/test_case_rsync/Dockerfile
Normal file
8
deploy/test_case_rsync/Dockerfile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
FROM alpine:3.6
|
||||||
|
|
||||||
|
RUN apk add --update --no-cache rsync
|
||||||
|
|
||||||
|
ADD ./run.sh /tmp/run.sh
|
||||||
|
ADD ./rsyncd.conf /etc/rsyncd.conf
|
||||||
|
|
||||||
|
CMD /bin/sh /tmp/run.sh
|
24
deploy/test_case_rsync/docker-compose.yml
Normal file
24
deploy/test_case_rsync/docker-compose.yml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
oj-rsync-master:
|
||||||
|
image: oj_rsync
|
||||||
|
container_name: oj-rsync
|
||||||
|
volumes:
|
||||||
|
- $PWD/data/backend/test_case:/test_case:ro
|
||||||
|
- $PWD/data/rsync_master:/log
|
||||||
|
environment:
|
||||||
|
- RSYNC_MODE=master
|
||||||
|
- RSYNC_USER=ojrsync
|
||||||
|
- RSYNC_PASSWORD=CHANGE_THIS_PASSWORD
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:873:873"
|
||||||
|
|
||||||
|
oj-rsync-slave:
|
||||||
|
image: oj-rsync
|
||||||
|
volumes:
|
||||||
|
- $PWD/test_case:/test_case
|
||||||
|
- $PWD/rsync_slave:/log
|
||||||
|
environment:
|
||||||
|
- RSYNC_MODE=slave
|
||||||
|
- RSYNC_USER=ojrsync
|
||||||
|
- RSYNC_PASSWORD=CHANGE_THIS_PASSWORD
|
12
deploy/test_case_rsync/rsyncd.conf
Normal file
12
deploy/test_case_rsync/rsyncd.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
port = 873
|
||||||
|
uid = root
|
||||||
|
gid = root
|
||||||
|
use chroot = yes
|
||||||
|
read only = yes
|
||||||
|
log file = /log/rsyncd.log
|
||||||
|
|
||||||
|
[testcase]
|
||||||
|
path = /test_case/
|
||||||
|
list = yes
|
||||||
|
auth users = ojrsync
|
||||||
|
secrets file = /etc/rsyncd.passwd
|
33
deploy/test_case_rsync/run.sh
Normal file
33
deploy/test_case_rsync/run.sh
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
slave_runner()
|
||||||
|
{
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
rsync -avzP --delete --progress --password-file=/etc/rsync_slave.passwd $RSYNC_USER@$RSYNC_MASTER_ADDR::testcase /test_case >> /log/rsync_slave.log
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
master_runner()
|
||||||
|
{
|
||||||
|
rsync --daemon --config=/etc/rsyncd.conf
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
sleep 60
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$RSYNC_MODE" = "master" ]; then
|
||||||
|
if [ ! -f "/etc/rsyncd.passwd" ]; then
|
||||||
|
echo "$RSYNC_USER:$RSYNC_PASSWORD" > /etc/rsyncd.passwd
|
||||||
|
fi
|
||||||
|
chmod 600 /etc/rsyncd.passwd
|
||||||
|
master_runner
|
||||||
|
else
|
||||||
|
if [ ! -f "/etc/rsync_slave.passwd" ]; then
|
||||||
|
echo "$RSYNC_PASSWORD" > /etc/rsync_slave.passwd
|
||||||
|
fi
|
||||||
|
chmod 600 /etc/rsync_slave.passwd
|
||||||
|
slave_runner
|
||||||
|
fi
|
@ -1,7 +1,7 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from judge.languages import language_names, spj_language_names
|
from judge.languages import language_names, spj_language_names
|
||||||
from utils.api import DateTimeTZField, UsernameSerializer, serializers
|
from utils.api import UsernameSerializer, serializers
|
||||||
|
|
||||||
from .models import Problem, ProblemRuleType, ProblemTag
|
from .models import Problem, ProblemRuleType, ProblemTag
|
||||||
from .utils import parse_problem_template
|
from .utils import parse_problem_template
|
||||||
@ -87,15 +87,8 @@ class CompileSPJSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
|
|
||||||
class BaseProblemSerializer(serializers.ModelSerializer):
|
class BaseProblemSerializer(serializers.ModelSerializer):
|
||||||
samples = serializers.JSONField()
|
|
||||||
test_case_score = serializers.JSONField()
|
|
||||||
languages = serializers.JSONField()
|
|
||||||
template = serializers.JSONField()
|
|
||||||
tags = serializers.SlugRelatedField(many=True, slug_field="name", read_only=True)
|
tags = serializers.SlugRelatedField(many=True, slug_field="name", read_only=True)
|
||||||
create_time = DateTimeTZField()
|
|
||||||
last_update_time = DateTimeTZField()
|
|
||||||
created_by = UsernameSerializer()
|
created_by = UsernameSerializer()
|
||||||
statistic_info = serializers.JSONField()
|
|
||||||
|
|
||||||
|
|
||||||
class ProblemAdminSerializer(BaseProblemSerializer):
|
class ProblemAdminSerializer(BaseProblemSerializer):
|
||||||
@ -104,12 +97,6 @@ class ProblemAdminSerializer(BaseProblemSerializer):
|
|||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class ContestProblemAdminSerializer(BaseProblemSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Problem
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ProblemSerializer(BaseProblemSerializer):
|
class ProblemSerializer(BaseProblemSerializer):
|
||||||
template = serializers.SerializerMethodField()
|
template = serializers.SerializerMethodField()
|
||||||
|
|
||||||
@ -121,21 +108,16 @@ class ProblemSerializer(BaseProblemSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Problem
|
model = Problem
|
||||||
exclude = ("contest", "test_case_score", "test_case_id", "visible", "is_public",
|
exclude = ("test_case_score", "test_case_id", "visible", "is_public",
|
||||||
"template", "spj_code", "spj_version", "spj_compile_ok")
|
"spj_code", "spj_version", "spj_compile_ok")
|
||||||
|
|
||||||
|
|
||||||
class ContestProblemSerializer(BaseProblemSerializer):
|
class ProblemSafeSerializer(BaseProblemSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Problem
|
model = Problem
|
||||||
exclude = ("test_case_score", "test_case_id", "visible", "is_public", "difficulty")
|
exclude = ("test_case_score", "test_case_id", "visible", "is_public",
|
||||||
|
"spj_code", "spj_version", "spj_compile_ok",
|
||||||
|
"difficulty", "submission_number", "accepted_number", "statistic_info")
|
||||||
class ContestProblemSafeSerializer(BaseProblemSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Problem
|
|
||||||
exclude = ("test_case_score", "test_case_id", "visible", "is_public", "difficulty",
|
|
||||||
"submission_number", "accepted_number", "statistic_info")
|
|
||||||
|
|
||||||
|
|
||||||
class ContestProblemMakePublicSerializer(serializers.Serializer):
|
class ContestProblemMakePublicSerializer(serializers.Serializer):
|
||||||
|
@ -16,7 +16,7 @@ from utils.api import APIView, CSRFExemptAPIView, validate_serializer
|
|||||||
from utils.shortcuts import rand_str, natural_sort_key
|
from utils.shortcuts import rand_str, natural_sort_key
|
||||||
|
|
||||||
from ..models import Problem, ProblemRuleType, ProblemTag
|
from ..models import Problem, ProblemRuleType, ProblemTag
|
||||||
from ..serializers import (CreateContestProblemSerializer, ContestProblemAdminSerializer, CompileSPJSerializer,
|
from ..serializers import (CreateContestProblemSerializer, CompileSPJSerializer,
|
||||||
CreateProblemSerializer, EditProblemSerializer, EditContestProblemSerializer,
|
CreateProblemSerializer, EditProblemSerializer, EditContestProblemSerializer,
|
||||||
ProblemAdminSerializer, TestCaseUploadForm, ContestProblemMakePublicSerializer)
|
ProblemAdminSerializer, TestCaseUploadForm, ContestProblemMakePublicSerializer)
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ class ContestProblemAPI(ProblemBase):
|
|||||||
except ProblemTag.DoesNotExist:
|
except ProblemTag.DoesNotExist:
|
||||||
tag = ProblemTag.objects.create(name=item)
|
tag = ProblemTag.objects.create(name=item)
|
||||||
problem.tags.add(tag)
|
problem.tags.add(tag)
|
||||||
return self.success(ContestProblemAdminSerializer(problem).data)
|
return self.success(ProblemAdminSerializer(problem).data)
|
||||||
|
|
||||||
@problem_permission_required
|
@problem_permission_required
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
@ -345,7 +345,7 @@ class ContestProblemAPI(ProblemBase):
|
|||||||
keyword = request.GET.get("keyword")
|
keyword = request.GET.get("keyword")
|
||||||
if keyword:
|
if keyword:
|
||||||
problems = problems.filter(title__contains=keyword)
|
problems = problems.filter(title__contains=keyword)
|
||||||
return self.success(self.paginate_data(request, problems, ContestProblemAdminSerializer))
|
return self.success(self.paginate_data(request, problems, ProblemAdminSerializer))
|
||||||
|
|
||||||
@validate_serializer(EditContestProblemSerializer)
|
@validate_serializer(EditContestProblemSerializer)
|
||||||
@problem_permission_required
|
@problem_permission_required
|
||||||
|
@ -3,8 +3,7 @@ from django.db.models import Q, Count
|
|||||||
from utils.api import APIView
|
from utils.api import APIView
|
||||||
from account.decorators import check_contest_permission
|
from account.decorators import check_contest_permission
|
||||||
from ..models import ProblemTag, Problem, ProblemRuleType
|
from ..models import ProblemTag, Problem, ProblemRuleType
|
||||||
from ..serializers import ProblemSerializer, TagSerializer
|
from ..serializers import ProblemSerializer, TagSerializer, ProblemSafeSerializer
|
||||||
from ..serializers import ContestProblemSerializer, ContestProblemSafeSerializer
|
|
||||||
from contest.models import ContestRuleType
|
from contest.models import ContestRuleType
|
||||||
|
|
||||||
|
|
||||||
@ -102,16 +101,16 @@ class ContestProblemAPI(APIView):
|
|||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exist.")
|
return self.error("Problem does not exist.")
|
||||||
if self.contest.problem_details_permission(request.user):
|
if self.contest.problem_details_permission(request.user):
|
||||||
problem_data = ContestProblemSerializer(problem).data
|
problem_data = ProblemSerializer(problem).data
|
||||||
self._add_problem_status(request, [problem_data, ])
|
self._add_problem_status(request, [problem_data, ])
|
||||||
else:
|
else:
|
||||||
problem_data = ContestProblemSafeSerializer(problem).data
|
problem_data = ProblemSafeSerializer(problem).data
|
||||||
return self.success(problem_data)
|
return self.success(problem_data)
|
||||||
|
|
||||||
contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True)
|
contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True)
|
||||||
if self.contest.problem_details_permission(request.user):
|
if self.contest.problem_details_permission(request.user):
|
||||||
data = ContestProblemSerializer(contest_problems, many=True).data
|
data = ProblemSerializer(contest_problems, many=True).data
|
||||||
self._add_problem_status(request, data)
|
self._add_problem_status(request, data)
|
||||||
else:
|
else:
|
||||||
data = ContestProblemSafeSerializer(contest_problems, many=True).data
|
data = ProblemSafeSerializer(contest_problems, many=True).data
|
||||||
return self.success(data)
|
return self.success(data)
|
||||||
|
@ -17,17 +17,15 @@ class ShareSubmissionSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
|
|
||||||
class SubmissionModelSerializer(serializers.ModelSerializer):
|
class SubmissionModelSerializer(serializers.ModelSerializer):
|
||||||
info = serializers.JSONField()
|
|
||||||
statistic_info = serializers.JSONField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Submission
|
model = Submission
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
# 不显示submission info的serializer, 用于ACM rule_type
|
# 不显示submission info的serializer, 用于ACM rule_type
|
||||||
class SubmissionSafeModelSerializer(serializers.ModelSerializer):
|
class SubmissionSafeModelSerializer(serializers.ModelSerializer):
|
||||||
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
|
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
|
||||||
statistic_info = serializers.JSONField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Submission
|
model = Submission
|
||||||
@ -36,7 +34,6 @@ class SubmissionSafeModelSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class SubmissionListSerializer(serializers.ModelSerializer):
|
class SubmissionListSerializer(serializers.ModelSerializer):
|
||||||
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
|
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
|
||||||
statistic_info = serializers.JSONField()
|
|
||||||
show_link = serializers.SerializerMethodField()
|
show_link = serializers.SerializerMethodField()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
class DateTimeTZField(serializers.DateTimeField):
|
|
||||||
def to_representation(self, value):
|
|
||||||
# value = timezone.localtime(value)
|
|
||||||
return super(DateTimeTZField, self).to_representation(value)
|
|
||||||
|
|
||||||
|
|
||||||
class UsernameSerializer(serializers.Serializer):
|
class UsernameSerializer(serializers.Serializer):
|
||||||
id = serializers.IntegerField()
|
id = serializers.IntegerField()
|
||||||
username = serializers.CharField()
|
username = serializers.CharField()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user