mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-11-04 14:32:19 +01:00 
			
		
		
		
	Send syntheses
This commit is contained in:
		@@ -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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {% if tfjmuser.team %}
 | 
				
			||||||
                    <dt class="col-xl-6 text-right">{% trans 'team'|capfirst %}</dt>
 | 
					                    <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>
 | 
					                    <dd class="col-xl-6"><a href="{% url "tournament:team_detail" pk=tfjmuser.team.pk %}">{{ tfjmuser.team }}</a></dd>
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {% if tfjmuser.birth_date %}
 | 
				
			||||||
                    <dt class="col-xl-6 text-right">{% trans 'birth date'|capfirst %}</dt>
 | 
					                    <dt class="col-xl-6 text-right">{% trans 'birth date'|capfirst %}</dt>
 | 
				
			||||||
                    <dd class="col-xl-6">{{ tfjmuser.birth_date }}</dd>
 | 
					                    <dd class="col-xl-6">{{ tfjmuser.birth_date }}</dd>
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {% if tfjmuser.participates %}
 | 
				
			||||||
                    <dt class="col-xl-6 text-right">{% trans 'gender'|capfirst %}</dt>
 | 
					                    <dt class="col-xl-6 text-right">{% trans 'gender'|capfirst %}</dt>
 | 
				
			||||||
                    <dd class="col-xl-6">{{ tfjmuser.get_gender_display }}</dd>
 | 
					                    <dd class="col-xl-6">{{ tfjmuser.get_gender_display }}</dd>
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {% if tfjmuser.address %}
 | 
				
			||||||
                    <dt class="col-xl-6 text-right">{% trans 'address'|capfirst %}</dt>
 | 
					                    <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>
 | 
					                    <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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {% if tfjmuser.phone_number %}
 | 
				
			||||||
                    <dt class="col-xl-6 text-right">{% trans 'phone number'|capfirst %}</dt>
 | 
					                    <dt class="col-xl-6 text-right">{% trans 'phone number'|capfirst %}</dt>
 | 
				
			||||||
                    <dd class="col-xl-6">{{ tfjmuser.phone_number }}</dd>
 | 
					                    <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>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								templates/tournament/syntheses_list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								templates/tournament/syntheses_list.html
									
									
									
									
									
										Normal file
									
								
							@@ -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 %}
 | 
				
			||||||
							
								
								
									
										18
									
								
								templates/tournament/syntheses_orga_list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								templates/tournament/syntheses_orga_list.html
									
									
									
									
									
										Normal file
									
								
							@@ -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>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user