498 lines
22 KiB
Python
498 lines
22 KiB
Python
from django.db.models import Q
|
|
from rest_framework.pagination import PageNumberPagination
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.utils.decorators import method_decorator
|
|
from django.core.files.base import ContentFile
|
|
from rest_framework.decorators import api_view, permission_classes
|
|
import base64
|
|
from cmath import inf
|
|
import csv
|
|
import importlib.util
|
|
import io
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import tempfile
|
|
from django.http import FileResponse, HttpResponse
|
|
from django.shortcuts import render
|
|
from time import sleep
|
|
from rest_framework.views import APIView
|
|
from rest_framework.response import Response
|
|
from rest_framework import status
|
|
from django.template.loader import get_template
|
|
import sympy
|
|
|
|
from .filters import ExosFilter
|
|
|
|
from .paginations import CustomPagination
|
|
|
|
from .pdfmaker import pdf_settings
|
|
|
|
from .models import generate_unique_code_step
|
|
|
|
from .utils import TexError, checkExoModelObject
|
|
|
|
import requests
|
|
|
|
from api.Generateur import Csv_generator, Generateur
|
|
|
|
from .models import Exercice, Tag
|
|
from .serializers import ExerciceCreateSerializer, ExerciceSerializer, TagSerializer
|
|
from users.serializers import UserSerializer
|
|
|
|
from rest_framework import permissions
|
|
# Create your views here.
|
|
|
|
|
|
|
|
|
|
class ExerciceAPI(APIView):
|
|
pagination_class = CustomPagination
|
|
def get(self, request, format=None):
|
|
steps = Exercice.objects.filter(private=False)
|
|
userExos = []
|
|
if request.user.is_authenticated:
|
|
steps = [s for s in steps if s.author.id != request.user.id]
|
|
userExos = request.user.exercice_set.all()
|
|
|
|
code = request.GET.get('code')
|
|
|
|
if code == 'pdf':
|
|
stepsListSorted = [s for s in steps if s.isPdf == True]
|
|
userExosListSorted = [s for s in userExos if s.isPdf == True]
|
|
elif code == 'web':
|
|
stepsListSorted = [s for s in steps if s.isWeb == True]
|
|
userExosListSorted = [s for s in userExos if s.isWeb == True]
|
|
if code == 'all':
|
|
stepsListSorted = steps
|
|
userExosListSorted = userExos
|
|
else:
|
|
stepsListSorted = steps
|
|
userExosListSorted = userExos
|
|
|
|
if code != 'all' and code != 'pdf' and code != "web":
|
|
exo = Exercice.objects.filter(id_code=code)[0]
|
|
isUser = False
|
|
if request.user == exo.author:
|
|
isUser = True
|
|
return Response({"data": {**ExerciceSerializer(exo).data, "isUser": isUser, "original": exo.origin.id_code if exo.origin != None else None, "author": UserSerializer(exo.author).data if exo.author != None else None, 'exo_model': { 'filename': exo.exo_model.name.split('/')[-1], "data": open(exo.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in [tt for tt in exo.tags.all() if tt.user == request.user]]}}, status=status.HTTP_200_OK)
|
|
else:
|
|
return Response({"data": {
|
|
"userExos": [{**ExerciceSerializer(ex).data,'isUser': True ,"original": ex.origin.id_code if ex.origin != None else None, "author": UserSerializer(ex.author).data if ex.author != None else None, "exo_model": {"filename": ex.exo_model.name.split('/')[-1], "data": open(
|
|
ex.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label':t.name} for t in ex.tags.all()]} for ex in userExosListSorted],
|
|
"publicList": [{**ExerciceSerializer(ex).data,'isUser': False, 'isRegistered': len(request.user.registeredExos.filter(id_code=ex.id_code)) != 0 if request.user.is_authenticated else None, "author": UserSerializer(ex.author).data if ex.author != None else None, "exo_model": {"filename": ex.exo_model.name.split('/')[-1], "data": open(
|
|
ex.exo_model.name, 'r').read()}, "original": ex.origin.id_code if ex.origin != None else None,
|
|
"tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in [tt for tt in ex.tags.all() if tt.user == request.user]]} for ex in stepsListSorted],
|
|
}}, status=status.HTTP_200_OK)
|
|
|
|
def post(self, request, format=None):
|
|
file = request.FILES['file']
|
|
name = request.data.get('name')
|
|
private = request.data.get('private')
|
|
consigne = request.data.get('consigne')
|
|
create_serializer = ExerciceCreateSerializer(
|
|
data={'exo_model': file, "consigne": consigne, "name": name, 'private': private}, context={'request': request})
|
|
if create_serializer.is_valid():
|
|
author = request.user if request.user.is_authenticated else None
|
|
new_exo = Exercice(consigne=consigne,
|
|
exo_model=create_serializer.validated_data['exo_model']['file'], name=name, author=author, private=create_serializer.validated_data['private'])
|
|
# Generateur(exo_model, 5)
|
|
|
|
new_exo.isPdf = create_serializer.validated_data['exo_model']['isPdf']
|
|
new_exo.isCsv = create_serializer.validated_data['exo_model']['isCsv']
|
|
new_exo.isWeb = create_serializer.validated_data['exo_model']['isWeb']
|
|
new_exo.save()
|
|
new_exo.exemple = {
|
|
# f'{"Csv" if new_exo.isCsv == True else ""}{"Web" if new_exo.isWeb == True else ""}',
|
|
'type': 'Csv' if new_exo.isCsv == True else 'Web' if new_exo.isWeb == True else None,
|
|
'data': Generateur(new_exo.exo_model.name, 5, 'csv' if new_exo.isCsv == True else 'web' if new_exo.isWeb == True else None, True) if new_exo.isCsv == True or new_exo.isWeb == True else None
|
|
}
|
|
new_exo.save()
|
|
# sleep(2)
|
|
|
|
return Response({"status": "200", "errors": {}, "data": {**ExerciceSerializer(new_exo).data, "author": UserSerializer(new_exo.author).data if new_exo.author != None else None, 'exo_model': {'filename': new_exo.exo_model.name.split('/')[-1], "data": open(new_exo.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in new_exo.tags.all()]}}, status=status.HTTP_200_OK)
|
|
print(create_serializer.errors, 'errs')
|
|
return Response({"status": "400", "errors": create_serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@method_decorator(login_required)
|
|
def put(self, request, format=None):
|
|
file = request.FILES['file']
|
|
name = request.data.get('name')
|
|
consigne = request.data.get('consigne')
|
|
id_code = request.data.get('id_code')
|
|
|
|
exo = Exercice.objects.filter(id_code=id_code)
|
|
if len(exo) == 0:
|
|
return Response({'status': "404", "data": {}},
|
|
status=status.HTTP_404_NOT_FOUND)
|
|
exo = exo[0]
|
|
if request.user != exo.author:
|
|
return Response({'status': "401", "data": {}},
|
|
status=status.HTTP_401_UNAUTHORIZED)
|
|
|
|
serializer = ExerciceCreateSerializer(
|
|
data={'exo_model': file, "consigne": consigne, "name": name})
|
|
errors = []
|
|
|
|
if serializer.is_valid():
|
|
exo.name = name
|
|
exo.consigne = consigne
|
|
exo.exo_model = serializer.validated_data['exo_model']['file']
|
|
|
|
exo.isPdf = serializer.validated_data['exo_model']['isPdf']
|
|
exo.isCsv = serializer.validated_data['exo_model']['isCsv']
|
|
exo.isWeb = serializer.validated_data['exo_model']['isWeb']
|
|
exo.save()
|
|
exo.exemple = {
|
|
# f'{"Csv" if new_exo.isCsv == True else ""}{"Web" if new_exo.isWeb == True else ""}',
|
|
'type': 'Csv' if exo.isCsv == True else 'Web' if exo.isWeb == True else None,
|
|
'data': Generateur(exo.exo_model.name, 5, 'csv' if exo.isCsv == True else 'web' if exo.isWeb == True else None, True) if exo.isCsv == True or exo.isWeb == True else None
|
|
}
|
|
exo.save()
|
|
|
|
return Response({"status": "200", "errors": {}, "data": ExerciceSerializer(exo).data}, status=status.HTTP_200_OK)
|
|
return Response({"status": "400", "errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@method_decorator(login_required)
|
|
def delete(self, request, format=None):
|
|
|
|
id_code = request.data.get('id_code')
|
|
exo = Exercice.objects.filter(id_code=id_code)
|
|
if len(exo) == 0:
|
|
return Response({'status': "404", "data": {}},
|
|
status=status.HTTP_404_NOT_FOUND)
|
|
exo = exo[0]
|
|
if request.user != exo.author:
|
|
return Response({'status': "401", "data": {}},
|
|
status=status.HTTP_401_UNAUTHORIZED)
|
|
|
|
exo.delete()
|
|
|
|
return Response({'status': "200", "data": id_code}, status=status.HTTP_200_OK)
|
|
|
|
|
|
|
|
@api_view(['GET'])
|
|
def getPublicList(request):
|
|
''' paginator = PageNumberPagination()
|
|
paginator.page_size = 10
|
|
person_objects = Exercice.objects.all()
|
|
result_page = paginator.paginate_queryset(person_objects, request) '''
|
|
#exos = Exercice.objects.all()
|
|
#return Response({'data': ExerciceSerializer(exos[8], context={'user_id': request.user.id_code if not request.user.is_anonymous else ''}).data}, status=status.HTTP_200_OK)
|
|
|
|
paginator = CustomPagination()
|
|
paginator.page_size = 22
|
|
|
|
exos = Exercice.objects.filter(private=False).filter(original=True)
|
|
|
|
if not request.user.is_anonymous:
|
|
# [ex for ex in exos if ex.author.id != request.user.id]
|
|
exos = exos.filter(~Q(author__id=request.user.id))
|
|
|
|
code = request.query_params.get('code')
|
|
|
|
if code == 'pdf':
|
|
exos = exos.filter(isPdf = True)#[s for s in exos if s.isPdf == True]
|
|
elif code == 'web':
|
|
exos = exos.filter(isWeb = True)#[s for s in exos if s.isWeb == True]
|
|
elif code == 'csv':
|
|
exos = exos.filter(isCsv = True)#[s for s in exos if s.isCsv == True]
|
|
exos = ExosFilter(request=request.GET, queryset=exos).qs
|
|
|
|
|
|
result_page = paginator.paginate_queryset(exos, request)
|
|
serializer = ExerciceSerializer(result_page, many=True, context={
|
|
'user_id': request.user.id_code if not request.user.is_anonymous else ''})
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def getUserExosList(request):
|
|
paginator = CustomPagination()
|
|
paginator.page_size = 22
|
|
|
|
|
|
exos = request.user.exercice_set.all()# Exercice.objects.filter(private=False).filter(original=True)
|
|
code = request.query_params.get('code')
|
|
|
|
if code == 'pdf':
|
|
exos = exos.filter(isPdf = True)#[s for s in exos if s.isPdf == True]
|
|
elif code == 'web':
|
|
exos = exos.filter(isWeb = True)#[s for s in exos if s.isWeb == True]
|
|
elif code == 'csv':
|
|
exos = exos.filter(isCsv = True)#[s for s in exos if s.isCsv == True]
|
|
exos = ExosFilter(request=request.GET, queryset=exos).qs
|
|
|
|
result_page = paginator.paginate_queryset(exos, request)
|
|
serializer = ExerciceSerializer(result_page, many=True, context={
|
|
'user_id': request.user.id_code if not request.user.is_anonymous else ''})
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
|
|
|
|
|
|
@api_view(['GET'])
|
|
def getExoModelFile(request):
|
|
|
|
|
|
id_code = request.query_params['id_code']
|
|
exo = Exercice.objects.filter(id_code=id_code)
|
|
if len(exo) == 0:
|
|
return Response({'errors': 'Not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
exo = exo[0]
|
|
model = exo.exo_model
|
|
print(model.name)
|
|
with open(model.name, 'r') as f:
|
|
|
|
response = HttpResponse(f.read(), content_type='text/x-python')
|
|
response['Content-Disposition'] = f'attachment;filename={model.name.split("/")[-1]}'
|
|
return response
|
|
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def fav(request):
|
|
code = request.data.get('code')
|
|
exo = Exercice.objects.filter(id_code=code)
|
|
if len(exo) == 0:
|
|
return Response({'data': {'msg': 'Not found'}}, status=status.HTTP_404_NOT_FOUND)
|
|
originExo = exo[0]
|
|
exo = exo[0]
|
|
with open(exo.exo_model.path, 'r') as f:
|
|
print(f.name.split('/')[-1])
|
|
exo.pk = None
|
|
exo.id = None
|
|
exo.id_code = generate_unique_code_step()
|
|
exo.author = request.user
|
|
exo.original = False
|
|
exo.origin = Exercice.objects.filter(id_code=code)[0]
|
|
exo.exo_model.save(f.name.split('/')[-1], ContentFile(f.read()))
|
|
exo._state.adding = True
|
|
exo.save()
|
|
|
|
|
|
return Response({'data': {'isRegistered': False}}, status=status.HTTP_200_OK)
|
|
|
|
|
|
class TagsAPI(APIView):
|
|
@method_decorator(login_required)
|
|
def get(self, request, format=None):
|
|
tags = request.user.tag_set.all()
|
|
return Response({"data": list(map(lambda tag: {**TagSerializer(tag).data, 'label': tag.name, "value": tag.id_code}, tags))}, status=status.HTTP_200_OK)
|
|
|
|
@method_decorator(login_required)
|
|
def post(self, request, format=None):
|
|
options = request.data.get('tags')
|
|
id_code = request.data.get('step')
|
|
exo = Exercice.objects.filter(id_code=id_code)
|
|
if len(exo) == 0:
|
|
return Response({'status': "404", "data": {}},
|
|
status=status.HTTP_404_NOT_FOUND)
|
|
exo = exo[0]
|
|
''' if request.user != exo.author:
|
|
return Response({'status': "401", "data": {}},
|
|
status=status.HTTP_401_UNAUTHORIZED) '''
|
|
tagsList = []
|
|
|
|
for o in options:
|
|
# print(o)
|
|
if o['value'].startswith('new_opt'):
|
|
newTag = Tag(name=o['label'], color=o['color'], user = request.user)
|
|
newTag.save()
|
|
exo.tags.add(newTag)
|
|
exo.save()
|
|
tagsList.append(
|
|
{'name': o['label'], 'color': o['color'], 'id_code': newTag.id_code})
|
|
else:
|
|
tagId = o['value']
|
|
tag = request.user.tag_set.filter(id_code=tagId)
|
|
if len(tag) == 0:
|
|
return Response({'errors': ''}, status=status.HTTP_400_BAD_REQUEST)
|
|
tag= tag[0]
|
|
exo.tags.add(tag)
|
|
exo.save()
|
|
tagsList.append(
|
|
{'name': o['label'], 'color': o['color'], 'id_code': tag.id_code})
|
|
return Response({'id_code': exo.id_code, 'tags': [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in exo.tags.all() if t.user == request.user]}, status=status.HTTP_200_OK)
|
|
|
|
@method_decorator(login_required)
|
|
def delete(self, request, format=None):
|
|
tagId = request.data.get('tag')
|
|
id_code = request.data.get('step')
|
|
exo = Exercice.objects.filter(id_code=id_code)
|
|
if len(exo) == 0:
|
|
return Response({'status': "404", "data": {}},
|
|
status=status.HTTP_404_NOT_FOUND)
|
|
tag = request.user.tag_set.filter(id_code=tagId)
|
|
if len(tag) == 0:
|
|
return Response({'errors': ''}, status=status.HTTP_400_BAD_REQUEST)
|
|
tag = tag[0]
|
|
exo = exo[0]
|
|
if request.user != exo.author:
|
|
if tag.user != request.user:
|
|
return Response({'status': "401", "data": {}},
|
|
status=status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
exo.tags.remove(tag)
|
|
exo.save()
|
|
return Response({'id_code': exo.id_code,'name': tag.name, 'tagId': tag.id_code,'tags': [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in exo.tags.all() if t.user == request.user]}, status=status.HTTP_200_OK)
|
|
|
|
|
|
class Editor(APIView):
|
|
def post(self, request, format=None):
|
|
code = request.data.get('code')
|
|
|
|
if code == None:
|
|
return Response([''], status=status.HTTP_200_OK)
|
|
|
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
with open(os.path.join(tempdir, "tmp.py"), 'w') as script:
|
|
script.write(code)
|
|
proc = subprocess.Popen(['python3.10', 'tmp.py', ],
|
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=tempdir)
|
|
print(open(os.path.join(tempdir, "tmp.py"), 'r').read())
|
|
out, err = proc.communicate()
|
|
out = out.decode().splitlines()
|
|
return Response({"out": out, "error": err.decode('utf-8').splitlines()}, status=status.HTTP_200_OK)
|
|
|
|
|
|
class CSV_Generator(APIView):
|
|
def get(self, request, code, format=None):
|
|
|
|
ex = Exercice.objects.filter(id_code=code)[0]
|
|
if ex.isCsv == False:
|
|
return Response({'error': "Bah non en fait"}, status=status.HTTP_401_UNAUTHORIZED)
|
|
|
|
model = ex.exo_model.name
|
|
consigne = ex.consigne
|
|
|
|
response = HttpResponse(content_type='text/csv')
|
|
response['Content-Disposition'] = 'attachment;filename="test.csv"'
|
|
writer = csv.writer(response, delimiter=',',
|
|
quotechar=',', quoting=csv.QUOTE_MINIMAL, dialect='excel') # mettre | comme sep un jour
|
|
|
|
Csv_generator(model, 10, 10, 10,
|
|
consigne, writer)
|
|
|
|
return response
|
|
|
|
|
|
class PDF(APIView):
|
|
def post(self, request, format=None):
|
|
print('exos', request.data.get('exos'))
|
|
exos = list(map(lambda ex: pdf_settings(
|
|
Exercice.objects.filter(id_code=ex['id_code'])[0].exo_model.name, 14, int(ex['numberInExo']), int(ex['numberOfExo']), 1, ex['consigne']), request.data.get('exos')))
|
|
|
|
# print(exos)
|
|
# dans str mettre space(0.5) replace by \hspace{0.5cm}
|
|
template_name = 'test.tex'
|
|
symbols = {
|
|
"≈": "\\approx",
|
|
'≠': '\\neq',
|
|
"≃": "\\simeq"
|
|
}
|
|
|
|
# a refaire pour supp les symbols
|
|
for e in range(len(exos)):
|
|
for exo in range(len(exos[e]['exos'])):
|
|
# print(exos[e]['exos'][exo])
|
|
|
|
exos[e]['exos'][exo]['calcul'] = sympy.latex(
|
|
exos[e]['exos'][exo]['calcul'])
|
|
|
|
exos[e]['exos'][exo]['calcul'] = exos[e]['exos'][exo]['calcul'].replace(
|
|
'≃', '\\ensuremath{\\simeq}')
|
|
exos[e]['exos'][exo]['calcul'] = exos[e]['exos'][exo]['calcul'].replace(
|
|
'≈', '\\ensurmath{\approx}')
|
|
exos[e]['exos'][exo]['calcul'] = exos[e]['exos'][exo]['calcul'].replace(
|
|
'≠', '\\ensuremath{\neq}')
|
|
|
|
exos[e]['exos'][exo]['correction'] = sympy.latex(
|
|
exos[e]['exos'][exo]['correction'])
|
|
|
|
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
|
|
'≃', '\\ensuremath{\\simeq}')
|
|
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
|
|
'≈', '\\ensurmath{\approx}')
|
|
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
|
|
'≠', '\\ensuremath{\neq}')
|
|
|
|
exp_list = re.findall(
|
|
r'\[([A-Za-z0-9_]+)\]', exos[e]['exos'][exo]['correction'])
|
|
red = '{red}'
|
|
for exp in exp_list:
|
|
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
|
|
f'[{exp}]', f'\\textcolor{red}{{{exp}}}')
|
|
|
|
context = {'exos': exos, 'title': request.data.get(
|
|
'title'), 'police': request.data.get('police')}
|
|
|
|
template = get_template('test.tex')
|
|
latex = template.render(context) # latex to compile
|
|
# print(latex)
|
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
direct = tempdir
|
|
with open(os.path.join(direct, 'tmp.tex'), 'x', encoding='utf-8') as f:
|
|
f.write(latex)
|
|
command = f'xelatex -interaction=batchmode tmp.tex'
|
|
try:
|
|
subprocess.run(command, shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
check=True,
|
|
cwd=direct)
|
|
except TexError:
|
|
raise TexError(log=log, source=latex,
|
|
template_name='test.tex')
|
|
try:
|
|
subprocess.run(command, shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
check=True,
|
|
cwd=direct)
|
|
except TexError:
|
|
raise TexError(log=log, source=latex,
|
|
template_name='test.tex')
|
|
|
|
with open(os.path.join(direct, 'tmp.pdf'), 'rb') as out:
|
|
|
|
pdf = out.read()
|
|
buffer = io.BytesIO(out.read())
|
|
fich_name = request.data.get('file')
|
|
if fich_name.count('.') >= 1:
|
|
ext = fich_name.split('.')[-1]
|
|
# print(ext)
|
|
if ext == 'pdf':
|
|
fich_name = fich_name
|
|
elif ext != 'pdf':
|
|
# print('nipe')
|
|
fich_name = fich_name.replace(f'.{ext}', '.pdf')
|
|
else:
|
|
fich_name = fich_name + '.pdf'
|
|
return Response({'pdf': base64.b64encode(pdf), 'filename': fich_name}, status=status.HTTP_200_OK)
|
|
''' return PDFResponse(base64.b64encode(pdf), filename=fich_name)
|
|
subprocess.run('ls', cwd=direct)
|
|
'''
|
|
|
|
|
|
class Test(APIView):
|
|
def get(self, request, format=None):
|
|
code = "VZRKLZ"
|
|
ex = Exercice.objects.filter(id_code=code)[0]
|
|
model = ex.exo_model
|
|
print('model', model.name)
|
|
oplist = Generateur(model.name, 2, 'calcul')
|
|
return Response({"data": oplist}, status=status.HTTP_200_OK)
|
|
|
|
|
|
class ExoModelApi(APIView):
|
|
def get(self, request, format=None):
|
|
code = request.GET.get('id_code')
|
|
exo = Exercice.objects.filter(id_code=code)[0]
|
|
print(exo.exo_model.name)
|
|
model = open(exo.exo_model.name, 'rb')
|
|
return FileResponse(model, status=status.HTTP_200_OK)
|