Send syntheses
This commit is contained in:
parent
26eacad2fd
commit
b55aa6f4f3
|
@ -110,7 +110,7 @@ class SynthesisViewSet(ModelViewSet):
|
||||||
queryset = Synthesis.objects.all()
|
queryset = Synthesis.objects.all()
|
||||||
serializer_class = SynthesisSerializer
|
serializer_class = SynthesisSerializer
|
||||||
filter_backends = [DjangoFilterBackend]
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ['team', 'team__trigram', 'dest', 'round', ]
|
filterset_fields = ['team', 'team__trigram', 'source', 'round', ]
|
||||||
|
|
||||||
|
|
||||||
# Routers provide an easy way of automatically determining the URL conf.
|
# Routers provide an easy way of automatically determining the URL conf.
|
||||||
|
|
|
@ -263,7 +263,7 @@ class Command(BaseCommand):
|
||||||
obj_dict = {
|
obj_dict = {
|
||||||
"file": args[0],
|
"file": args[0],
|
||||||
"team": Team.objects.get(pk=args[1]),
|
"team": Team.objects.get(pk=args[1]),
|
||||||
"dest": "defender" if args[3] == "DEFENDER" else "opponent"
|
"source": "defender" if args[3] == "DEFENDER" else "opponent"
|
||||||
if args[4] == "OPPOSANT" else "rapporteur",
|
if args[4] == "OPPOSANT" else "rapporteur",
|
||||||
"uploaded_at": args[4],
|
"uploaded_at": args[4],
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,10 @@ class Solution(Document):
|
||||||
verbose_name=_("final solution"),
|
verbose_name=_("final solution"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tournament(self):
|
||||||
|
return Tournament.get_final() if self.final else self.team.tournament
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("solution")
|
verbose_name = _("solution")
|
||||||
verbose_name_plural = _("solutions")
|
verbose_name_plural = _("solutions")
|
||||||
|
@ -261,14 +265,14 @@ class Synthesis(Document):
|
||||||
verbose_name=_("team"),
|
verbose_name=_("team"),
|
||||||
)
|
)
|
||||||
|
|
||||||
dest = models.CharField(
|
source = models.CharField(
|
||||||
max_length=16,
|
max_length=16,
|
||||||
choices=[
|
choices=[
|
||||||
("defender", _("Defender")),
|
("defender", _("Defender")),
|
||||||
("opponent", _("Opponent")),
|
("opponent", _("Opponent")),
|
||||||
("rapporteur", _("Rapporteur")),
|
("rapporteur", _("Rapporteur")),
|
||||||
],
|
],
|
||||||
verbose_name=_("dest"),
|
verbose_name=_("source"),
|
||||||
)
|
)
|
||||||
|
|
||||||
round = models.PositiveSmallIntegerField(
|
round = models.PositiveSmallIntegerField(
|
||||||
|
@ -284,14 +288,18 @@ class Synthesis(Document):
|
||||||
verbose_name=_("final synthesis"),
|
verbose_name=_("final synthesis"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tournament(self):
|
||||||
|
return Tournament.get_final() if self.final else self.team.tournament
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("synthesis")
|
verbose_name = _("synthesis")
|
||||||
verbose_name_plural = _("syntheses")
|
verbose_name_plural = _("syntheses")
|
||||||
unique_together = ('team', 'dest', 'round', 'final',)
|
unique_together = ('team', 'source', 'round', 'final',)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return _("Synthesis of team {trigram} that is {dest} for problem {problem}")\
|
return _("Synthesis of team {trigram} that is {source} for the tournament {tournament}")\
|
||||||
.format(trigram=self.team.trigram, dest=self.dest, problem=self.problem)
|
.format(trigram=self.team.trigram, source=self.source, tournament=self.tournament)
|
||||||
|
|
||||||
|
|
||||||
class Config(models.Model):
|
class Config(models.Model):
|
||||||
|
|
|
@ -58,4 +58,4 @@ class SolutionForm(forms.ModelForm):
|
||||||
class SynthesisForm(forms.ModelForm):
|
class SynthesisForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Synthesis
|
model = Synthesis
|
||||||
fields = ('file', 'dest',)
|
fields = ('file', 'source', 'round',)
|
||||||
|
|
|
@ -64,10 +64,22 @@ class Tournament(models.Model):
|
||||||
verbose_name=_("year"),
|
verbose_name=_("year"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def linked_organizers(self):
|
||||||
|
return ['<a href="{url}">'.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '</a>'
|
||||||
|
for user in self.organizers.all()]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def solutions(self):
|
def solutions(self):
|
||||||
from member.models import Solution
|
from member.models import Solution
|
||||||
return Solution.objects.filter(team__tournament=self)
|
return Solution.objects.filter(final=self.final) if self.final \
|
||||||
|
else Solution.objects.filter(team__tournament=self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def syntheses(self):
|
||||||
|
from member.models import Synthesis
|
||||||
|
return Synthesis.objects.filter(final=self.final) if self.final \
|
||||||
|
else Synthesis.objects.filter(team__tournament=self)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_final(cls):
|
def get_final(cls):
|
||||||
|
|
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django_tables2 import A
|
from django_tables2 import A
|
||||||
|
|
||||||
from member.models import Solution
|
from member.models import Solution, Synthesis
|
||||||
from .models import Tournament, Team
|
from .models import Tournament, Team
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ class SolutionTable(tables.Table):
|
||||||
|
|
||||||
tournament = tables.LinkColumn(
|
tournament = tables.LinkColumn(
|
||||||
"tournament:detail",
|
"tournament:detail",
|
||||||
args=[A("team.tournament.pk")],
|
args=[A("tournament.pk")],
|
||||||
accessor=A("team.tournament"),
|
accessor=A("tournament"),
|
||||||
)
|
)
|
||||||
|
|
||||||
file = tables.LinkColumn(
|
file = tables.LinkColumn(
|
||||||
|
@ -75,6 +75,17 @@ class SolutionTable(tables.Table):
|
||||||
|
|
||||||
|
|
||||||
class SynthesisTable(tables.Table):
|
class SynthesisTable(tables.Table):
|
||||||
|
team = tables.LinkColumn(
|
||||||
|
"tournament:team_detail",
|
||||||
|
args=[A("team.pk")],
|
||||||
|
)
|
||||||
|
|
||||||
|
tournament = tables.LinkColumn(
|
||||||
|
"tournament:detail",
|
||||||
|
args=[A("tournament.pk")],
|
||||||
|
accessor=A("tournament"),
|
||||||
|
)
|
||||||
|
|
||||||
file = tables.LinkColumn(
|
file = tables.LinkColumn(
|
||||||
"document",
|
"document",
|
||||||
args=[A("file")],
|
args=[A("file")],
|
||||||
|
@ -89,8 +100,8 @@ class SynthesisTable(tables.Table):
|
||||||
return _("Download")
|
return _("Download")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Team
|
model = Synthesis
|
||||||
fields = ("team", "team.tournament", "round", "dest", "uploaded_at", "file", )
|
fields = ("team", "tournament", "round", "source", "uploaded_at", "file", )
|
||||||
attrs = {
|
attrs = {
|
||||||
'class': 'table table-condensed table-striped table-hover'
|
'class': 'table table-condensed table-striped table-hover'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.views.generic import RedirectView
|
|
||||||
|
|
||||||
from .views import TournamentListView, TournamentCreateView, TournamentDetailView, TournamentUpdateView,\
|
from .views import TournamentListView, TournamentCreateView, TournamentDetailView, TournamentUpdateView, \
|
||||||
TeamDetailView, TeamUpdateView, AddOrganizerView, SolutionsView, SolutionsOrgaListView
|
TeamDetailView, TeamUpdateView, AddOrganizerView, SolutionsView, SolutionsOrgaListView, SynthesesView,\
|
||||||
|
SynthesesOrgaListView
|
||||||
|
|
||||||
app_name = "tournament"
|
app_name = "tournament"
|
||||||
|
|
||||||
|
@ -16,6 +16,6 @@ urlpatterns = [
|
||||||
path("add-organizer/", AddOrganizerView.as_view(), name="add_organizer"),
|
path("add-organizer/", AddOrganizerView.as_view(), name="add_organizer"),
|
||||||
path("solutions/", SolutionsView.as_view(), name="solutions"),
|
path("solutions/", SolutionsView.as_view(), name="solutions"),
|
||||||
path("all-solutions/", SolutionsOrgaListView.as_view(), name="all_solutions"),
|
path("all-solutions/", SolutionsOrgaListView.as_view(), name="all_solutions"),
|
||||||
path("syntheses/", RedirectView.as_view(pattern_name="index"), name="syntheses"),
|
path("syntheses/", SynthesesView.as_view(), name="syntheses"),
|
||||||
path("all_syntheses/", RedirectView.as_view(pattern_name="index"), name="all_syntheses"),
|
path("all_syntheses/", SynthesesOrgaListView.as_view(), name="all_syntheses"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -10,13 +10,13 @@ from django.shortcuts import redirect
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic import DetailView, CreateView, UpdateView
|
from django.views.generic import DetailView, CreateView, UpdateView
|
||||||
from django.views.generic.edit import FormMixin, BaseFormView
|
from django.views.generic.edit import BaseFormView
|
||||||
from django_tables2.views import SingleTableView
|
from django_tables2.views import SingleTableView
|
||||||
|
|
||||||
from member.models import TFJMUser, Solution
|
from member.models import TFJMUser, Solution, Synthesis
|
||||||
from .forms import TournamentForm, OrganizerForm, TeamForm, SolutionForm
|
from .forms import TournamentForm, OrganizerForm, TeamForm, SolutionForm, SynthesisForm
|
||||||
from .models import Tournament, Team
|
from .models import Tournament, Team
|
||||||
from .tables import TournamentTable, TeamTable, SolutionTable
|
from .tables import TournamentTable, TeamTable, SolutionTable, SynthesisTable
|
||||||
|
|
||||||
|
|
||||||
class AdminMixin(LoginRequiredMixin):
|
class AdminMixin(LoginRequiredMixin):
|
||||||
|
@ -26,6 +26,13 @@ class AdminMixin(LoginRequiredMixin):
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class OrgaMixin(LoginRequiredMixin):
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
if not request.user.organizes:
|
||||||
|
raise PermissionDenied
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TeamMixin(LoginRequiredMixin):
|
class TeamMixin(LoginRequiredMixin):
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if not request.user.team:
|
if not request.user.team:
|
||||||
|
@ -181,14 +188,6 @@ class SolutionsView(TeamMixin, BaseFormView, SingleTableView):
|
||||||
|
|
||||||
return super().post(request, *args, **kwargs)
|
return super().post(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
context["tournaments"] = \
|
|
||||||
Tournament.objects if self.request.user.admin else self.request.user.organized_tournaments
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
if not self.request.user.admin:
|
if not self.request.user.admin:
|
||||||
|
@ -211,16 +210,11 @@ class SolutionsView(TeamMixin, BaseFormView, SingleTableView):
|
||||||
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def form_invalid(self, form):
|
|
||||||
print(form.errors)
|
|
||||||
|
|
||||||
return super().form_invalid(form)
|
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse_lazy("tournament:solutions")
|
return reverse_lazy("tournament:solutions")
|
||||||
|
|
||||||
|
|
||||||
class SolutionsOrgaListView(AdminMixin, SingleTableView):
|
class SolutionsOrgaListView(OrgaMixin, SingleTableView):
|
||||||
model = Solution
|
model = Solution
|
||||||
table_class = SolutionTable
|
table_class = SolutionTable
|
||||||
template_name = "tournament/solutions_orga_list.html"
|
template_name = "tournament/solutions_orga_list.html"
|
||||||
|
@ -262,3 +256,104 @@ class SolutionsOrgaListView(AdminMixin, SingleTableView):
|
||||||
if not self.request.user.admin:
|
if not self.request.user.admin:
|
||||||
qs = qs.filter(team__tournament__organizers=self.request.user)
|
qs = qs.filter(team__tournament__organizers=self.request.user)
|
||||||
return qs.order_by('team__tournament__date_start', 'team__tournament__name', 'team__trigram', 'problem',)
|
return qs.order_by('team__tournament__date_start', 'team__tournament__name', 'team__trigram', 'problem',)
|
||||||
|
|
||||||
|
|
||||||
|
class SynthesesView(TeamMixin, BaseFormView, SingleTableView):
|
||||||
|
model = Synthesis
|
||||||
|
table_class = SynthesisTable
|
||||||
|
form_class = SynthesisForm
|
||||||
|
template_name = "tournament/syntheses_list.html"
|
||||||
|
extra_context = dict(title=_("Syntheses"))
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
if "zip" in request.POST:
|
||||||
|
syntheses = request.user.team.syntheses
|
||||||
|
|
||||||
|
out = BytesIO()
|
||||||
|
zf = zipfile.ZipFile(out, "w")
|
||||||
|
|
||||||
|
for synthesis in syntheses:
|
||||||
|
zf.write(synthesis.file.path, str(synthesis) + ".pdf")
|
||||||
|
|
||||||
|
zf.close()
|
||||||
|
|
||||||
|
resp = HttpResponse(out.getvalue(), content_type="application/x-zip-compressed")
|
||||||
|
resp['Content-Disposition'] = 'attachment; filename={}'\
|
||||||
|
.format(_("Syntheses for team {team}.zip")
|
||||||
|
.format(team=str(request.user.team)).replace(" ", "%20"))
|
||||||
|
return resp
|
||||||
|
|
||||||
|
return super().post(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = super().get_queryset()
|
||||||
|
if not self.request.user.admin:
|
||||||
|
qs = qs.filter(team=self.request.user.team)
|
||||||
|
return qs.order_by('team__tournament__date_start', 'team__tournament__name', 'team__trigram', 'round',
|
||||||
|
'source',)
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
synthesis = form.instance
|
||||||
|
synthesis.team = self.request.user.team
|
||||||
|
synthesis.final = synthesis.team.selected_for_final
|
||||||
|
prev_syn = Synthesis.objects.filter(team=synthesis.team, round=synthesis.round, source=synthesis.source,
|
||||||
|
final=synthesis.final)
|
||||||
|
for syn in prev_syn.all():
|
||||||
|
syn.delete()
|
||||||
|
alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
|
||||||
|
id = ""
|
||||||
|
for _ in range(64):
|
||||||
|
id += random.choice(alphabet)
|
||||||
|
synthesis.file.name = id
|
||||||
|
synthesis.save()
|
||||||
|
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse_lazy("tournament:syntheses")
|
||||||
|
|
||||||
|
|
||||||
|
class SynthesesOrgaListView(OrgaMixin, SingleTableView):
|
||||||
|
model = Synthesis
|
||||||
|
table_class = SynthesisTable
|
||||||
|
template_name = "tournament/syntheses_orga_list.html"
|
||||||
|
extra_context = dict(title=_("All syntheses"))
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
if "tournament_zip" in request.POST:
|
||||||
|
tournament = Tournament.objects.get(pk=request.POST["tournament_zip"][0])
|
||||||
|
syntheses = tournament.syntheses
|
||||||
|
if not request.user.admin and request.user not in tournament.organizers.all():
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
out = BytesIO()
|
||||||
|
zf = zipfile.ZipFile(out, "w")
|
||||||
|
|
||||||
|
for synthesis in syntheses:
|
||||||
|
zf.write(synthesis.file.path, str(synthesis) + ".pdf")
|
||||||
|
|
||||||
|
zf.close()
|
||||||
|
|
||||||
|
resp = HttpResponse(out.getvalue(), content_type="application/x-zip-compressed")
|
||||||
|
resp['Content-Disposition'] = 'attachment; filename={}'\
|
||||||
|
.format(_("Syntheses for tournament {tournament}.zip")
|
||||||
|
.format(tournament=str(tournament)).replace(" ", "%20"))
|
||||||
|
return resp
|
||||||
|
|
||||||
|
return self.get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
context["tournaments"] = \
|
||||||
|
Tournament.objects if self.request.user.admin else self.request.user.organized_tournaments
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = super().get_queryset()
|
||||||
|
if not self.request.user.admin:
|
||||||
|
qs = qs.filter(team__tournament__organizers=self.request.user)
|
||||||
|
return qs.order_by('team__tournament__date_start', 'team__tournament__name', 'team__trigram', 'round',
|
||||||
|
'source',)
|
||||||
|
|
||||||
|
|
|
@ -12,23 +12,33 @@
|
||||||
<dt class="col-xl-6 text-right">{% trans 'role'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'role'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ tfjmuser.get_role_display }}</dd>
|
<dd class="col-xl-6">{{ tfjmuser.get_role_display }}</dd>
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'team'|capfirst %}</dt>
|
{% if tfjmuser.team %}
|
||||||
<dd class="col-xl-6"><a href="{% url "tournament:team_detail" pk=tfjmuser.team.pk %}">{{ tfjmuser.team }}</a></dd>
|
<dt class="col-xl-6 text-right">{% trans 'team'|capfirst %}</dt>
|
||||||
|
<dd class="col-xl-6"><a href="{% url "tournament:team_detail" pk=tfjmuser.team.pk %}">{{ tfjmuser.team }}</a></dd>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'birth date'|capfirst %}</dt>
|
{% if tfjmuser.birth_date %}
|
||||||
<dd class="col-xl-6">{{ tfjmuser.birth_date }}</dd>
|
<dt class="col-xl-6 text-right">{% trans 'birth date'|capfirst %}</dt>
|
||||||
|
<dd class="col-xl-6">{{ tfjmuser.birth_date }}</dd>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'gender'|capfirst %}</dt>
|
{% if tfjmuser.participates %}
|
||||||
<dd class="col-xl-6">{{ tfjmuser.get_gender_display }}</dd>
|
<dt class="col-xl-6 text-right">{% trans 'gender'|capfirst %}</dt>
|
||||||
|
<dd class="col-xl-6">{{ tfjmuser.get_gender_display }}</dd>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'address'|capfirst %}</dt>
|
{% if tfjmuser.address %}
|
||||||
<dd class="col-xl-6">{{ tfjmuser.address }}, {{ tfjmuser.postal_code }}, {{ tfjmuser.city }}{% if tfjmuser.country != "France" %}, {{ tfjmuser.country }}{% endif %}</dd>
|
<dt class="col-xl-6 text-right">{% trans 'address'|capfirst %}</dt>
|
||||||
|
<dd class="col-xl-6">{{ tfjmuser.address }}, {{ tfjmuser.postal_code }}, {{ tfjmuser.city }}{% if tfjmuser.country != "France" %}, {{ tfjmuser.country }}{% endif %}</dd>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'email'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'email'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6"><a href="mailto:{{ tfjmuser.email }}">{{ tfjmuser.email }}</a></dd>
|
<dd class="col-xl-6"><a href="mailto:{{ tfjmuser.email }}">{{ tfjmuser.email }}</a></dd>
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'phone number'|capfirst %}</dt>
|
{% if tfjmuser.phone_number %}
|
||||||
<dd class="col-xl-6">{{ tfjmuser.phone_number }}</dd>
|
<dt class="col-xl-6 text-right">{% trans 'phone number'|capfirst %}</dt>
|
||||||
|
<dd class="col-xl-6">{{ tfjmuser.phone_number }}</dd>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if tfjmuser.role == '3participant' %}
|
{% if tfjmuser.role == '3participant' %}
|
||||||
<dt class="col-xl-6 text-right">{% trans 'school'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'school'|capfirst %}</dt>
|
||||||
|
@ -53,9 +63,9 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if tfjmuser.role == '2coach' %}
|
{% if tfjmuser.role != '3participant' %}
|
||||||
<dt class="col-xl-6 text-right">{% trans 'description'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'description'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ tfjmuser.description }}</dd>
|
<dd class="col-xl-6">{{ tfjmuser.description|default_if_none:"" }}</dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load i18n crispy_forms_filters django_tables2 %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if form %}
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
<button class="btn btn-block btn-success">{% trans "Submit" %}</button>
|
||||||
|
</form>
|
||||||
|
<hr>
|
||||||
|
{% endif %}
|
||||||
|
{% render_table table %}
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load i18n django_tables2 %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% render_table table %}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="btn-group btn-block">
|
||||||
|
{% for tournament in tournaments.all %}
|
||||||
|
<button name="tournament_zip" value="{{ tournament.id }}" class="btn btn-success">{% blocktrans %}{{ tournament }} — ZIP{% endblocktrans %}</button>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -10,7 +10,7 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
<dt class="col-xl-6 text-right">{% trans 'organizers'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'organizers'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ tournament.organizers.all|join:", " }}</dd>
|
<dd class="col-xl-6">{% autoescape off %}{{ tournament.linked_organizers|join:", " }}{% endautoescape %}</dd>
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'size'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'size'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ tournament.size }}</dd>
|
<dd class="col-xl-6">{{ tournament.size }}</dd>
|
||||||
|
|
Loading…
Reference in New Issue