question as csv
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
|
import csv
|
||||||
import json
|
import json
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from colorfield.fields import ColorField
|
from colorfield.fields import ColorField
|
||||||
@@ -12,6 +12,7 @@ from filer.fields.file import FilerFileField
|
|||||||
|
|
||||||
from lib.core.db.models.base import SharedPermissionBase
|
from lib.core.db.models.base import SharedPermissionBase
|
||||||
from lib.core.db.models.mixins import DateAware, AuthorAware, DescriptionAware, NameAware, PublishedAware
|
from lib.core.db.models.mixins import DateAware, AuthorAware, DescriptionAware, NameAware, PublishedAware
|
||||||
|
from tablequizwiki.settings import BASE_DIR
|
||||||
|
|
||||||
|
|
||||||
class MediaFile(NameAware, DateAware, AuthorAware, DescriptionAware):
|
class MediaFile(NameAware, DateAware, AuthorAware, DescriptionAware):
|
||||||
@@ -88,37 +89,59 @@ class Question(DateAware, AuthorAware, PublishedAware, DescriptionAware):
|
|||||||
| models.Q(buzzword__icontains=term) \
|
| models.Q(buzzword__icontains=term) \
|
||||||
| models.Q(labels__name__icontains=term)
|
| models.Q(labels__name__icontains=term)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_by_tearchterm(term, queryset=None):
|
def get_by_tearchterm(term, queryset=None):
|
||||||
if not queryset:
|
if not queryset:
|
||||||
queryset = Question.objects
|
queryset = Question.objects
|
||||||
return queryset.filter(Question.searchdomain(term)).annotate(cnt=models.Count('id'))
|
return queryset.filter(Question.searchdomain(term)).annotate(cnt=models.Count('id'))
|
||||||
|
|
||||||
|
def to_view(self, for_players: bool = False):
|
||||||
|
ret = {}
|
||||||
|
ret['name'] = '{}{}'.format(self.name, f'({self.buzzword})' if self.buzzword else '')
|
||||||
|
ret['question'] = self.question
|
||||||
|
if self.description:
|
||||||
|
ret['question'] += ' \n\n------------------------------\n\n' + self.description
|
||||||
|
ret['awnser'] = self.awnser
|
||||||
|
ret['level'] = self.level.value
|
||||||
|
ret['medias'] = []
|
||||||
|
ret['links'] = []
|
||||||
|
for media in self.medias.all():
|
||||||
|
ret.setdefault('medias', []).append(os.path.basename(media.file.path))
|
||||||
|
for link in self.links.all():
|
||||||
|
ret.setdefault('links', []).append(link.url)
|
||||||
|
ret['question'] = mark_safe(ret['question'].replace('\n', '\n<br />'))
|
||||||
|
return ret
|
||||||
|
|
||||||
def to_view(self, for_players: bool = False):
|
@property
|
||||||
ret = {}
|
def zippath(self):
|
||||||
ret['name'] = '{}{}'.format(self.name, f'({self.buzzword})' if self.buzzword else '')
|
return str(BASE_DIR) + f'/filestore/zip/question.{self.id}.zip'
|
||||||
ret['question'] = self.question
|
|
||||||
if self.description:
|
|
||||||
ret['question'] += ' \n\n------------------------------\n\n' + self.description
|
|
||||||
ret['awnser'] = self.awnser
|
|
||||||
ret['level'] = self.level.value
|
|
||||||
ret['medias'] = []
|
|
||||||
ret['links'] = []
|
|
||||||
for media in self.medias.all():
|
|
||||||
ret.setdefault('medias', []).append(os.path.basename(media.file.path))
|
|
||||||
for link in self.links.all():
|
|
||||||
ret.setdefault('links', []).append(link.url)
|
|
||||||
ret['question'] = mark_safe(ret['question'].replace('\n', '\n<br />'))
|
|
||||||
logging.error(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pdfpath(self):
|
||||||
|
return str(BASE_DIR) + f'/filestore/pdf/question.{self.id}.pdf'
|
||||||
|
|
||||||
def default_json(o):
|
@property
|
||||||
if isinstance(o, (MediaFile,)):
|
def csvpath(self):
|
||||||
return str(o)
|
return str(BASE_DIR) + f'/filestore/csv/question.{self.id}.csv'
|
||||||
return json.dumps(model_to_dict(o))
|
|
||||||
|
def default_json(o):
|
||||||
|
if isinstance(o, (MediaFile,)):
|
||||||
|
return str(o)
|
||||||
|
return json.dumps(model_to_dict(o))
|
||||||
|
|
||||||
|
def to_csv(self, fh=None):
|
||||||
|
if fh:
|
||||||
|
cf = fh
|
||||||
|
else:
|
||||||
|
cf = open(self.csvpath, 'w')
|
||||||
|
items = self.to_view()
|
||||||
|
keys = items.keys()
|
||||||
|
dw = csv.DictWriter(cf, fieldnames=list(keys))
|
||||||
|
dw.writeheader()
|
||||||
|
dw.writerow(items)
|
||||||
|
if not fh:
|
||||||
|
cf.close()
|
||||||
|
return cf if fh else self.csvpath
|
||||||
|
|
||||||
|
|
||||||
class QuestionVersion(DateAware, AuthorAware):
|
class QuestionVersion(DateAware, AuthorAware):
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h3>Questions</h3>
|
||||||
<form action="/questions" method="get" id="search_q_form">
|
<form action="/questions" method="get" id="search_q_form">
|
||||||
<div id="question-search-field" class="row mb-5 mt-5">
|
<div id="question-search-field" class="row mb-5 mt-5">
|
||||||
<div class="col-12 p-0">
|
<div class="col-12 p-0">
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
<div class="col-3">Question</div>
|
<div class="col-3">Question</div>
|
||||||
<div class="col-1">Files</div>
|
<div class="col-1">Files</div>
|
||||||
<div class="col-1">Labels</div>
|
<div class="col-1">Labels</div>
|
||||||
|
<div class="col-1"><i class="fa fa-download"></i></div>
|
||||||
</div>
|
</div>
|
||||||
{% for q in items %}
|
{% for q in items %}
|
||||||
<div class="row p-2">
|
<div class="row p-2">
|
||||||
@@ -36,6 +38,9 @@
|
|||||||
{% if not forloop.last %},{% endif %}
|
{% if not forloop.last %},{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-1">
|
||||||
|
<a href="/questions/{{ q.id }}/csv" target="_blank">CSV</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ from content.views import public
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('questions/', public.search_question, name='search-questions'),
|
path('questions/', public.search_question, name='search-questions'),
|
||||||
|
path('questions/<int:id>/csv/', public.as_csv, name='csv-question'),
|
||||||
path('', public.search_question, name='search-questions'),
|
path('', public.search_question, name='search-questions'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from django.http import HttpResponseNotFound, HttpResponse, HttpResponseBadRequest
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
from content.models import Question
|
from content.models import Question
|
||||||
@@ -12,3 +13,14 @@ def search_question(request):
|
|||||||
else:
|
else:
|
||||||
items = published.all()[:10]
|
items = published.all()[:10]
|
||||||
return render(request, 'questions.html', {'items': items})
|
return render(request, 'questions.html', {'items': items})
|
||||||
|
|
||||||
|
|
||||||
|
def as_csv(request, **kwargs):
|
||||||
|
try:
|
||||||
|
q = Question.objects.get(id=kwargs['id'])
|
||||||
|
response = HttpResponse(content_type='text/csv')
|
||||||
|
return q.to_csv(fh=response)
|
||||||
|
except KeyError:
|
||||||
|
return HttpResponseBadRequest('No id given')
|
||||||
|
except Question.DoesNotExist:
|
||||||
|
return HttpResponseNotFound('Question not found')
|
||||||
|
|||||||
@@ -62,13 +62,18 @@ class Quiz(AuthorAware, DateAware, PublishedAware):
|
|||||||
return self.pdfpath
|
return self.pdfpath
|
||||||
|
|
||||||
def to_csv(self, fh=None):
|
def to_csv(self, fh=None):
|
||||||
with open(self.csvpath, 'w') as cf:
|
if fh:
|
||||||
items = self.to_view()['items']
|
cf = fh
|
||||||
keys = items[0].keys()
|
else:
|
||||||
dw = csv.DictWriter(cf, fieldnames=list(keys))
|
cf = open(self.csvpath, 'w')
|
||||||
dw.writeheader()
|
items = self.to_view()['items']
|
||||||
dw.writerows(items)
|
keys = items[0].keys()
|
||||||
return self.csvpath
|
dw = csv.DictWriter(cf, fieldnames=list(keys))
|
||||||
|
dw.writeheader()
|
||||||
|
dw.writerows(items)
|
||||||
|
if not fh:
|
||||||
|
cf.close()
|
||||||
|
return cf if fh else self.csvpath
|
||||||
|
|
||||||
def to_zip(self, fh=None):
|
def to_zip(self, fh=None):
|
||||||
with zipfile.ZipFile(self.zippath, 'w') as zf:
|
with zipfile.ZipFile(self.zippath, 'w') as zf:
|
||||||
|
|||||||
@@ -11,31 +11,40 @@
|
|||||||
-moz-border-radius: 4px;
|
-moz-border-radius: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group-unstyled .input-group-addon {
|
.input-group-unstyled .input-group-addon {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free.min.css?token=5f65fb5684" rel="stylesheet" />
|
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free.min.css?token=5f65fb5684" rel="stylesheet"/>
|
||||||
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free-v4-shims.min.css?token=5f65fb5684" rel="stylesheet" />
|
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free-v4-shims.min.css?token=5f65fb5684" rel="stylesheet"/>
|
||||||
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free-v5-font-face.min.css?token=5f65fb5684" rel="stylesheet" />
|
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free-v5-font-face.min.css?token=5f65fb5684" rel="stylesheet"/>
|
||||||
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free-v4-font-face.min.css?token=5f65fb5684" rel="stylesheet" />
|
<link href="https://ka-f.fontawesome.com/releases/v6.5.2/css/free-v4-font-face.min.css?token=5f65fb5684" rel="stylesheet"/>
|
||||||
{# <script src="https://kit.fontawesome.com/5f65fb5684.js" crossorigin="anonymous"></script> #}
|
{# <script src="https://kit.fontawesome.com/5f65fb5684.js" crossorigin="anonymous"></script> #}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container mt-2">
|
<div class="container mt-2">
|
||||||
<header>
|
<header>
|
||||||
<h1>Tablequiz DB</h1>
|
<div class="row">
|
||||||
<nav>
|
<div class="col-5">
|
||||||
<a class="nav-item" href="/questions/">Questions</a>
|
<h1>Tablequiz DB</h1>
|
||||||
<a class="nav-item" href="/quizes/">Quizes</a>
|
</div>
|
||||||
</nav>
|
<div class="col-7" style="vertical-align: bottom">
|
||||||
</header>
|
<nav style="vertical-align: bottom; width: auto; justify-content: flex-end" class="navbar right">
|
||||||
{% block content %}
|
<a class="nav-item p-3 btn btn-outline-dark mx-2" href="/questions/">Questions</a>
|
||||||
{% endblock %}
|
<a class="nav-item p-3 btn btn-outline-dark mx-2" href="/quizes/">Quizes</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<hr class="my-3 mx-0 p-0" />
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user