From 71b162a5fde7be78c5b63d4881cc3876465a7ce5 Mon Sep 17 00:00:00 2001 From: Costantino Date: Fri, 30 Sep 2022 17:33:55 +0200 Subject: [PATCH] =?utf8?q?-=20Implementazione=20funzionalit=C3=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 2 +- .idea/socoin_atlas.iml | 2 +- requirements.txt | 2 +- sistema/datatables.py | 193 ++++++++++++++++++++ sistema/forms.py | 48 +++++ sistema/models.py | 14 +- sistema/templates/add_mod_localita.html | 44 +++++ sistema/templates/add_mod_tipologia.html | 44 +++++ sistema/templates/base.html | 39 +++- sistema/templates/home.html | 2 +- sistema/templates/localita_list.html | 105 +++++++++++ sistema/templates/multimedia_list.html | 63 +++++++ sistema/templates/percorsi_list.html | 10 + sistema/templates/poi_list.html | 104 +++++++++++ sistema/templates/tipo_multimedia_list.html | 102 +++++++++++ sistema/urls.py | 36 +++- sistema/views.py | 178 +++++++++++++++++- socoin_atlas/settings.py | 4 +- utenti/datatables.py | 52 ++++++ utenti/forms.py | 2 +- utenti/templates/admin_list.html | 65 +++++++ utenti/templates/clienti_list.html | 65 +++++++ utenti/templates/tour_operator_list.html | 65 +++++++ utenti/urls.py | 12 +- utenti/views.py | 20 +- 25 files changed, 1250 insertions(+), 23 deletions(-) create mode 100644 sistema/datatables.py create mode 100644 sistema/templates/add_mod_localita.html create mode 100644 sistema/templates/add_mod_tipologia.html create mode 100644 sistema/templates/localita_list.html create mode 100644 sistema/templates/multimedia_list.html create mode 100644 sistema/templates/percorsi_list.html create mode 100644 sistema/templates/poi_list.html create mode 100644 sistema/templates/tipo_multimedia_list.html create mode 100644 utenti/datatables.py create mode 100644 utenti/templates/admin_list.html create mode 100644 utenti/templates/clienti_list.html create mode 100644 utenti/templates/tour_operator_list.html diff --git a/.idea/misc.xml b/.idea/misc.xml index ec83ff9..d28790d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/socoin_atlas.iml b/.idea/socoin_atlas.iml index f89b1a8..a312c3a 100644 --- a/.idea/socoin_atlas.iml +++ b/.idea/socoin_atlas.iml @@ -16,7 +16,7 @@ - + diff --git a/requirements.txt b/requirements.txt index 3797751..bff547c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ django-braces==1.15.0 django-crispy-forms==1.14.0 djangorestframework==3.14.0 djangorestframework-simplejwt==5.2.0 -mysqlclient==2.1.1 +#mysqlclient==2.1.1 PyJWT==2.5.0 pytz==2022.2.1 sqlparse==0.4.3 diff --git a/sistema/datatables.py b/sistema/datatables.py new file mode 100644 index 0000000..90f0e27 --- /dev/null +++ b/sistema/datatables.py @@ -0,0 +1,193 @@ +from django_datatables_view.base_datatable_view import BaseDatatableView +from django.utils.html import escape +from django.db.models import Q + +from sistema.models import Localita, Multimedia, TipologiaMultimedia, Percorso, PointOfInterest, Feedback + + +class LocalitaDatatables(BaseDatatableView): + model = Localita + columns = ['id', 'descrizione', 'provincia', 'cap', 'regione', 'mod', 'del'] + order_columns = ['id', 'descrizione', 'provincia', 'cap', 'regione', '', ''] + + def get_initial_queryset(self): + return self.model.objects.filter(is_active=True) + + def render_column(self, row, column): + if column == 'id': + return escape('{0}'.format(row.pk)) + if column == 'descrizione': + return escape('{0}'.format(row.descrizione)) + if column == 'provincia': + return escape('{0}'.format(row.provincia)) + if column == 'cap': + return escape('{0}'.format(row.cap)) + if column == 'regione': + return escape('{0}'.format(row.regione)) + if column == 'mod': + return '' % row.pk + if column == 'del': + return '' % row.pk + else: + return super(LocalitaDatatables, self).render_column(row, column) + + def filter_queryset(self, qs): + search = self.request.GET.get('search[value]', None) + if search: + qs = qs.filter(Q(descrizione__icontains=search) | Q(provincia__icontains=search) + | Q(cap__icontains=search) | Q(regione__icontains=search)) + return qs + + +class MultimediaDatatables(BaseDatatableView): + model = Multimedia + columns = ['id', 'tipologia', 'nome', 'descrizione', 'testo', 'mod', 'del'] + order_columns = ['id', 'tipologia', 'nome', 'descrizione', 'testo', 'mod', 'del'] + + def get_initial_queryset(self): + return self.model.objects.filter(is_active=True) + + def render_column(self, row, column): + if column == 'id': + return escape('{0}'.format(row.pk)) + if column == 'tipologia': + return escape('{0}'.format(row.tipologia.nome)) + if column == 'nome': + return escape('{0}'.format(row.provincia)) + if column == 'descrizione': + return escape('{0}'.format(row.descrizione)) + if column == 'testo': + return escape('{0}'.format(row.testo)) + if column == 'mod': + return '' #% row.pk + if column == 'del': + return '' #% row.pk + else: + return super(MultimediaDatatables, self).render_column(row, column) + + def filter_queryset(self, qs): + search = self.request.GET.get('search[value]', None) + if search: + qs = qs.filter(Q(descrizione__icontains=search) | Q(nome__icontains=search) + | Q(tipologia__nome__icontains=search)) + return qs + + +class TipoMultimediaDatatables(BaseDatatableView): + model = TipologiaMultimedia + columns = ['id', 'nome', 'mod', 'del'] + order_columns = ['id', 'nome', 'mod', 'del'] + + def get_initial_queryset(self): + return self.model.objects.filter(is_active=True) + + def render_column(self, row, column): + if column == 'id': + return escape('{0}'.format(row.pk)) + if column == 'nome': + return escape('{0}'.format(row.nome)) + if column == 'mod': + return '' % row.pk + if column == 'del': + return '' % row.pk + else: + return super(TipoMultimediaDatatables, self).render_column(row, column) + + def filter_queryset(self, qs): + search = self.request.GET.get('search[value]', None) + if search: + qs = qs.filter(Q(nome__icontains=search)) + return qs + + +class PercorsoDatatables(BaseDatatableView): + model = Percorso + columns = ['id', 'nome', 'descrizione', 'testo', 'mod', 'del'] + order_columns = ['id', 'nome', 'descrizione', 'testo', 'mod', 'del'] + + def get_initial_queryset(self): + return self.model.objects.filter(is_active=True) + + def render_column(self, row, column): + if column == 'id': + return escape('{0}'.format(row.pk)) + if column == 'nome': + return escape('{0}'.format(row.nome)) + if column == 'descrizione': + return escape('{0}'.format(row.descrizione)) + if column == 'testo': + return escape('{0}'.format(row.testo)) + if column == 'mod': + return '' #% row.pk + if column == 'del': + return '' #% row.pk + else: + return super(PercorsoDatatables, self).render_column(row, column) + + def filter_queryset(self, qs): + search = self.request.GET.get('search[value]', None) + if search: + qs = qs.filter(Q(nome__icontains=search) | Q(descrizione__icontains=search) | Q(testo__icontains=search)) + return qs + + +class PoiDatatables(BaseDatatableView): + model = PointOfInterest + columns = ['id', 'nome', 'lat', 'long', 'mod', 'del'] + order_columns = ['id', 'nome', 'lat', 'long', 'mod', 'del'] + + def get_initial_queryset(self): + return self.model.objects.filter(is_active=True) + + def render_column(self, row, column): + if column == 'id': + return escape('{0}'.format(row.pk)) + if column == 'nome': + return escape('{0}'.format(row.nome)) + if column == 'lat': + return escape('{0}'.format(row.lat)) + if column == 'long': + return escape('{0}'.format(row.long)) + if column == 'mod': + return '' #% row.pk + if column == 'del': + return '' #% row.pk + else: + return super(PoiDatatables, self).render_column(row, column) + + def filter_queryset(self, qs): + search = self.request.GET.get('search[value]', None) + if search: + qs = qs.filter(Q(nome__icontains=search) | Q(lat__icontains=search) | Q(long__icontains=search)) + return qs + + +class FeedbackDatatables(BaseDatatableView): + model = Feedback + columns = ['id', 'utente', 'valutazione', 'commento', 'mod', 'del'] + order_columns = ['id', 'utente', 'valutazione', 'commento', 'mod', 'del'] + + def get_initial_queryset(self): + return self.model.objects.filter(is_active=True) + + def render_column(self, row, column): + if column == 'id': + return escape('{0}'.format(row.pk)) + if column == 'utente': + return escape('{0}'.format(row.utente.username)) + if column == 'valutazione': + return escape('{0}'.format(row.valutazione)) + if column == 'commento': + return escape('{0}'.format(row.commento)) + if column == 'mod': + return '' #% row.pk + if column == 'del': + return '' #% row.pk + else: + return super(FeedbackDatatables, self).render_column(row, column) + + def filter_queryset(self, qs): + search = self.request.GET.get('search[value]', None) + if search: + qs = qs.filter(Q(utente__icontains=search) | Q(valutazione__icontains=search)) + return qs \ No newline at end of file diff --git a/sistema/forms.py b/sistema/forms.py index e69de29..df266ea 100644 --- a/sistema/forms.py +++ b/sistema/forms.py @@ -0,0 +1,48 @@ +from django.contrib.auth.forms import * + +from sistema.models import Localita, TipologiaMultimedia + + +class LocalitaForm(forms.ModelForm): + class Meta: + model = Localita + exclude = ('is_active',) + + descrizione = forms.CharField( + label="Nome", + max_length=255, + widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'}) + ) + + provincia = forms.CharField( + label="Provincia", + max_length=20, + widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'}) + ) + + cap = forms.CharField( + label="Cap", + max_length=10, + widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'}) + ) + + regione = forms.CharField( + label="Regione", + max_length=50, + widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'}) + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + +class TipoMultimediaForm(forms.ModelForm): + class Meta: + model = TipologiaMultimedia + exclude = ('is_active',) + + nome = forms.CharField( + label="Nome tipologia", + max_length=255, + widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'tipo_multimedia_form'}) + ) \ No newline at end of file diff --git a/sistema/models.py b/sistema/models.py index ec42a5d..a6f9a98 100644 --- a/sistema/models.py +++ b/sistema/models.py @@ -5,9 +5,9 @@ from django.utils import timezone class Localita(models.Model): descrizione = models.CharField(max_length=255, null=False) - provincia = models.CharField(max_length=5, null=True, blank=True) - cap = models.CharField(max_length=5, null=True, blank=True) - regione = models.CharField(max_length=5, null=True, blank=True) + provincia = models.CharField(max_length=50, null=True, blank=True) + cap = models.CharField(max_length=10, null=True, blank=True) + regione = models.CharField(max_length=50, null=True, blank=True) is_active = models.BooleanField(default=True) @@ -16,28 +16,33 @@ class Gestisce(models.Model): localita = models.ForeignKey(Localita, on_delete=models.DO_NOTHING) data_inizio = models.DateTimeField(auto_now_add=False, default=timezone.now, null=True, blank=True) data_fine = models.DateTimeField(null=True, blank=True) + is_active = models.BooleanField(default=True) class Percorso(models.Model): nome = models.CharField(max_length=255, null=False) descrizione = models.CharField(max_length=255, null=False) testo = models.TextField(max_length=255, null=False) + is_active = models.BooleanField(default=True) class PointOfInterest(models.Model): nome = models.CharField(max_length=255, null=False) lat = models.FloatField() long = models.FloatField() + is_active = models.BooleanField(default=True) class Tappa(models.Model): percorso = models.ForeignKey(Percorso, on_delete=models.DO_NOTHING) poi = models.ForeignKey(PointOfInterest, on_delete=models.DO_NOTHING) ordine = models.IntegerField() + is_active = models.BooleanField(default=True) class TipologiaMultimedia(models.Model): nome = models.CharField(max_length=255, null=False) + is_active = models.BooleanField(default=True) class Multimedia(models.Model): @@ -46,9 +51,12 @@ class Multimedia(models.Model): nome = models.CharField(max_length=255, null=False) descrizione = models.CharField(max_length=255, null=False) testo = models.TextField(max_length=255, null=False) + is_active = models.BooleanField(default=True) class Feedback(models.Model): utente = models.ForeignKey(User, on_delete=models.DO_NOTHING) percorso = models.ForeignKey(Percorso, on_delete=models.DO_NOTHING) valutazione = models.IntegerField() + commento = models.TextField(max_length=255, null=True, blank=True) + is_active = models.BooleanField(default=True) diff --git a/sistema/templates/add_mod_localita.html b/sistema/templates/add_mod_localita.html new file mode 100644 index 0000000..4db31d8 --- /dev/null +++ b/sistema/templates/add_mod_localita.html @@ -0,0 +1,44 @@ +{% extends 'base.html' %} +{% load static %} +{% load crispy_forms_tags %} +{% block content %} + +
+
+

Gestione località

+
+
+ {% if form.instance.pk %} +

Modifica la località #{{ form.instance.pk }}

+ {% else %} +

Registra una nuova località nel sistema

+ {% endif %} +
+ +
+
{% csrf_token %} + {% if form.instance.pk %} + + + {% endif %} + {{form | crispy }} +
+ + +
+
+ +
+
+
+ + + + + +{% endblock %} \ No newline at end of file diff --git a/sistema/templates/add_mod_tipologia.html b/sistema/templates/add_mod_tipologia.html new file mode 100644 index 0000000..f66fed5 --- /dev/null +++ b/sistema/templates/add_mod_tipologia.html @@ -0,0 +1,44 @@ +{% extends 'base.html' %} +{% load static %} +{% load crispy_forms_tags %} +{% block content %} + +
+
+

Tipologia multimedia

+
+
+ {% if form.instance.pk %} +

Modifica la tipologia #{{ form.instance.pk }}

+ {% else %} +

Registra una nuova tipologia di multimedia nel sistema

+ {% endif %} +
+ +
+
{% csrf_token %} + {% if form.instance.pk %} + + + {% endif %} + {{form | crispy }} +
+ + +
+
+ +
+
+
+ + + + + +{% endblock %} \ No newline at end of file diff --git a/sistema/templates/base.html b/sistema/templates/base.html index caf29b5..5b94b50 100644 --- a/sistema/templates/base.html +++ b/sistema/templates/base.html @@ -138,18 +138,43 @@ diff --git a/sistema/templates/home.html b/sistema/templates/home.html index 97bab53..b3bc64a 100644 --- a/sistema/templates/home.html +++ b/sistema/templates/home.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} {% load static %} {% block content %} - CIAO + CIAO, {{ request.session.roles }} {% endblock %} \ No newline at end of file diff --git a/sistema/templates/localita_list.html b/sistema/templates/localita_list.html new file mode 100644 index 0000000..1e597f1 --- /dev/null +++ b/sistema/templates/localita_list.html @@ -0,0 +1,105 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
+
+

Gestione località

+ +
+
+

Lista località

+ + + +
+ +
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ +
+
+ + +{% endblock %} \ No newline at end of file diff --git a/sistema/templates/multimedia_list.html b/sistema/templates/multimedia_list.html new file mode 100644 index 0000000..3b909ef --- /dev/null +++ b/sistema/templates/multimedia_list.html @@ -0,0 +1,63 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
+
+

Gestione multimedia

+ +
+
+

Lista multimedia

+ + + +
+ +
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ +
+
+ + +{% endblock %} \ No newline at end of file diff --git a/sistema/templates/percorsi_list.html b/sistema/templates/percorsi_list.html new file mode 100644 index 0000000..566549b --- /dev/null +++ b/sistema/templates/percorsi_list.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + \ No newline at end of file diff --git a/sistema/templates/poi_list.html b/sistema/templates/poi_list.html new file mode 100644 index 0000000..42fb6da --- /dev/null +++ b/sistema/templates/poi_list.html @@ -0,0 +1,104 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
+
+

Gestione punti di interesse

+ +
+
+

Lista punti di interesse

+ + + +
+ +
+
+
+ + + + + + + + + + + + + + +
+
+
+
+ +
+
+ + +{% endblock %} \ No newline at end of file diff --git a/sistema/templates/tipo_multimedia_list.html b/sistema/templates/tipo_multimedia_list.html new file mode 100644 index 0000000..2002b6f --- /dev/null +++ b/sistema/templates/tipo_multimedia_list.html @@ -0,0 +1,102 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
+
+

Gestione tipologia multimedia

+ +
+
+

Lista tipologie di multimedia

+ + + +
+ +
+
+
+ + + + + + + + + + + + +
+
+
+
+ +
+
+ + +{% endblock %} \ No newline at end of file diff --git a/sistema/urls.py b/sistema/urls.py index 2b04ed4..625b6aa 100644 --- a/sistema/urls.py +++ b/sistema/urls.py @@ -1,7 +1,39 @@ from django.urls import path -from sistema.views import Home +from sistema.datatables import LocalitaDatatables, MultimediaDatatables, TipoMultimediaDatatables, PercorsoDatatables, \ + PoiDatatables, FeedbackDatatables +from sistema.views import Home, LocalitaListView, MultimediaListView, PuntiInteresseListView, \ + TipologiaMultimediaListView, PercorsiListView, LocalitaView, TipoMultimediaView, PoiView urlpatterns = [ - path('home/', Home.as_view(), name='home'), + path('', Home.as_view(), name='home'), + + ## TEMPLATEVIEWS ## + path('localita_list/', LocalitaListView.as_view(), name='localita_list'), + path('multimedia_list/', MultimediaListView.as_view(), name='multimedia_list'), + path('poi_list/', PuntiInteresseListView.as_view(), name='poi_list'), + path('tipo_multimedia_list/', TipologiaMultimediaListView.as_view(), name='tipo_multimedia_list'), + path('percorsi_list/', PercorsiListView.as_view(), name='percorsi_list'), + + ## DATATABLES ## + path('localita_datatables/', LocalitaDatatables.as_view(), name='localita_datatables'), + path('multimedia_datatables/', MultimediaDatatables.as_view(), name='multimedia_datatables'), + path('tipo_multimedia_datatables/', TipoMultimediaDatatables.as_view(), name='tipo_multimedia_datatables'), + path('percorso_datatables/', PercorsoDatatables.as_view(), name='percorso_datatables'), + path('poi_datatables/', PoiDatatables.as_view(), name='poi_datatables'), + path('feedback_datatables/', FeedbackDatatables.as_view(), name='feedback_datatables'), + + ## LOCALITA ## + path('localita/', LocalitaView.as_view(), name='localita'), + path('mod_localita//', LocalitaView.as_view(), name='mod_localita'), + + ## TIPOLOGIA MODALITA ## + path('tipo_multimedia/', TipoMultimediaView.as_view(), name='tipo_multimedia'), + path('mod_tipo_multimedia//', TipoMultimediaView.as_view(), name='mod_tipo_multimedia'), + + ## PUNTO DI INTERESSE ## + path('poi/', PoiView.as_view(), name='poi'), + path('mod_poi//', PoiView.as_view(), name='mod_poi'), + + ] diff --git a/sistema/views.py b/sistema/views.py index 02645f1..67cce9d 100644 --- a/sistema/views.py +++ b/sistema/views.py @@ -1,9 +1,183 @@ -from django.shortcuts import render +from django.contrib import messages +from django.http import JsonResponse +from django.shortcuts import render, redirect +from django.urls import reverse from django.views import View +from django.views.generic import TemplateView +from rest_framework import status +from sistema.forms import LocalitaForm, TipoMultimediaForm +from sistema.models import Localita, TipologiaMultimedia from utenti.mixins import CustomLoginRequiredMixin -class Home(View):#CustomLoginRequiredMixin +class LocalitaListView(TemplateView): + template_name = 'localita_list.html' + + +class PuntiInteresseListView(TemplateView): + template_name = 'poi_list.html' + + +class TipologiaMultimediaListView(TemplateView): + template_name = 'tipo_multimedia_list.html' + + +class MultimediaListView(TemplateView): + template_name = 'multimedia_list.html' + + +class PercorsiListView(TemplateView): + template_name = 'percorsi_list.html' + + +class Home(View): # CustomLoginRequiredMixin def get(self, request): return render(request, 'home.html', {}) + + +class LocalitaView(View): + def add_localita(self, request): + form = LocalitaForm(request.POST) + if form.is_valid(): + form.save() + + messages.add_message(request, messages.INFO, 'Nuova località inserita con successo.') + else: + errors = '' + for err in form.errors.as_data(): + errors += '
  • ' + err + '
  • ' + messages.add_message(request, messages.ERROR, 'Errore nell\'inserimento della località. Controlla il form.') + + def mod_localita(self, request): + form = LocalitaForm(request.POST, instance=Localita.objects.get(pk=int(self.request.POST.get('pk')))) + if form.is_valid(): + form.save() + + messages.add_message(request, messages.INFO, 'Località aggiornata con successo.') + else: + errors = '' + for err in form.errors.as_data(): + errors += '
  • ' + err + '
  • ' + messages.add_message(request, messages.ERROR, 'Errore nell\'aggiornamento della località. Controlla il form.') + + def del_localita(self, request): + localita = Localita.objects.get(pk=int(request.GET.get('pk'))) + localita.is_active = False + localita.save() + + def get(self, request, *args, **kwargs): + if request.GET.get('method') == 'del': + self.del_localita(request) + + return JsonResponse({'response': 'Località eliminata con successo'}, status=status.HTTP_200_OK) + elif 'pk' in kwargs: + return render(request, 'add_mod_localita.html', {'form': LocalitaForm(instance=Localita.objects.get(pk=int(self.kwargs['pk'])))}) + else: + return render(request, 'add_mod_localita.html', {'form': LocalitaForm()}) + + def post(self, request, *args, **kwargs): + if 'mod' in request.POST: + self.mod_localita(request) + else: + self.add_localita(request) + + return redirect(reverse('sistema:localita_list')) + + +class TipoMultimediaView(View): + def add_tipologia(self, request): + form = TipoMultimediaForm(request.POST) + if form.is_valid(): + form.save() + + messages.add_message(request, messages.INFO, 'Nuova tipologia inserita con successo.') + else: + errors = '' + for err in form.errors.as_data(): + errors += '
  • ' + err + '
  • ' + messages.add_message(request, messages.ERROR, 'Errore nell\'inserimento della tipologia. Controlla il form.') + + def mod_tipologia(self, request): + form = TipoMultimediaForm(request.POST, instance=TipologiaMultimedia.objects.get(pk=int(self.request.POST.get('pk')))) + if form.is_valid(): + form.save() + + messages.add_message(request, messages.INFO, 'Tipologia aggiornata con successo.') + else: + errors = '' + for err in form.errors.as_data(): + errors += '
  • ' + err + '
  • ' + messages.add_message(request, messages.ERROR, 'Errore nell\'aggiornamento della tipologia. Controlla il form.') + + def del_tipologia(self, request): + tipologia = TipologiaMultimedia.objects.get(pk=int(request.GET.get('pk'))) + tipologia.is_active = False + tipologia.save() + + def get(self, request, *args, **kwargs): + if request.GET.get('method') == 'del': + self.del_tipologia(request) + + return JsonResponse({'response': 'Tipologia eliminata con successo'}, status=status.HTTP_200_OK) + elif 'pk' in kwargs: + return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm(instance=TipologiaMultimedia.objects.get(pk=int(self.kwargs['pk'])))}) + else: + return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm()}) + + def post(self, request, *args, **kwargs): + if 'mod' in request.POST: + self.mod_tipologia(request) + else: + self.add_tipologia(request) + + return redirect(reverse('sistema:tipo_multimedia_list')) + + +class PoiView(View): + def add_poi(self, request): + form = TipoMultimediaForm(request.POST) + if form.is_valid(): + form.save() + + messages.add_message(request, messages.INFO, 'Nuova punto di interesse inserito con successo.') + else: + errors = '' + for err in form.errors.as_data(): + errors += '
  • ' + err + '
  • ' + messages.add_message(request, messages.ERROR, 'Errore nell\'inserimento del punto di interesse. Controlla il form.') + + def mod_poi(self, request): + form = TipoMultimediaForm(request.POST, instance=TipologiaMultimedia.objects.get(pk=int(self.request.POST.get('pk')))) + if form.is_valid(): + form.save() + + messages.add_message(request, messages.INFO, 'Punto di interesse aggiornata con successo.') + else: + errors = '' + for err in form.errors.as_data(): + errors += '
  • ' + err + '
  • ' + messages.add_message(request, messages.ERROR, 'Errore nell\'aggiornamento del punto di interesse. Controlla il form.') + + def del_poi(self, request): + tipologia = TipologiaMultimedia.objects.get(pk=int(request.GET.get('pk'))) + tipologia.is_active = False + tipologia.save() + + def get(self, request, *args, **kwargs): + if request.GET.get('method') == 'del': + self.del_poi(request) + + return JsonResponse({'response': 'Punto di interesse eliminato con successo'}, status=status.HTTP_200_OK) + elif 'pk' in kwargs: + return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm(instance=TipologiaMultimedia.objects.get(pk=int(self.kwargs['pk'])))}) + else: + return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm()}) + + def post(self, request, *args, **kwargs): + if 'mod' in request.POST: + self.mod_poi(request) + else: + self.add_poi(request) + + return redirect(reverse('sistema:tipo_multimedia_list')) \ No newline at end of file diff --git a/socoin_atlas/settings.py b/socoin_atlas/settings.py index 3e95406..f7d5f67 100644 --- a/socoin_atlas/settings.py +++ b/socoin_atlas/settings.py @@ -90,7 +90,7 @@ DATABASES = { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'socoin_atlas', 'USER': 'root', - 'PASSWORD': "password", + 'PASSWORD': "", 'HOST': '127.0.0.1', # Or an IP Address that your DB is hosted on 'PORT': '3306', 'AUTOCOMMIT': True, @@ -146,6 +146,6 @@ STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -CLIENTI_GROUPS = 'CLIENTI' +CLIENTI_GROUPS = 'CLIENTE' TOUR_OPERATOR_GROUPS = 'TOUR_OPERATOR' ADMIN_GROUPS = 'ADMIN' \ No newline at end of file diff --git a/utenti/datatables.py b/utenti/datatables.py new file mode 100644 index 0000000..8f6d0a8 --- /dev/null +++ b/utenti/datatables.py @@ -0,0 +1,52 @@ +from django.contrib.auth.models import User +from django_datatables_view.base_datatable_view import BaseDatatableView +from django.utils.html import escape +from django.db.models import Q + +from socoin_atlas import settings + + +class UserDatatables(BaseDatatableView): + model = User + columns = ['id', 'first_name', 'last_name', 'username', 'email', 'last_login', 'mod', 'del'] + order_columns = ['id', 'first_name', 'last_name', 'username', 'email', 'last_login', '', ''] + + def get_initial_queryset(self): + role = self.request.GET.get('role') + + if role: + if role == settings.ADMIN_GROUPS: + return self.model.objects.filter(groups__name=settings.ADMIN_GROUPS, is_active=True) + elif role == settings.TOUR_OPERATOR_GROUPS: + return self.model.objects.filter(groups__name=settings.TOUR_OPERATOR_GROUPS, is_active=True) + elif role == settings.CLIENTI_GROUPS: + return self.model.objects.filter(groups__name=settings.CLIENTI_GROUPS, is_active=True) + else: + return self.model.objects.none() + + def render_column(self, row, column): + if column == 'id': + return escape('{0}'.format(row.pk)) + if column == 'first_name': + return escape('{0}'.format(row.first_name)) + if column == 'last_name': + return escape('{0}'.format(row.last_name)) + if column == 'username': + return escape('{0}'.format(row.username)) + if column == 'email': + return escape('{0}'.format(row.email) or '') + if column == 'last_login': + return escape('{0}'.format(row.last_login or '')) + if column == 'mod': + return '' #% row.pk + if column == 'del': + return '' #% row.pk + else: + return super(UserDatatables, self).render_column(row, column) + + def filter_queryset(self, qs): + search = self.request.GET.get('search[value]', None) + if search: + qs = qs.filter(Q(first_name__icontains=search) | Q(last_name__icontains=search) + | Q(username__icontains=search) | Q(email__icontains=search)) + return qs \ No newline at end of file diff --git a/utenti/forms.py b/utenti/forms.py index 74ed065..22c4b1d 100644 --- a/utenti/forms.py +++ b/utenti/forms.py @@ -11,7 +11,7 @@ class FormLogin(forms.Form): class RegistrationForm(UserCreationForm): class Meta: model = User - fields = ['username', 'first_name', 'last_name', 'password1', 'password2'] + fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2'] def save(self, commit=True): user = super().save(commit=False) diff --git a/utenti/templates/admin_list.html b/utenti/templates/admin_list.html new file mode 100644 index 0000000..d275f31 --- /dev/null +++ b/utenti/templates/admin_list.html @@ -0,0 +1,65 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
    +
    +

    Gestione amministratori

    + +
    +
    +

    Lista amministratori

    + + + +
    + +
    +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +
    + + +{% endblock %} \ No newline at end of file diff --git a/utenti/templates/clienti_list.html b/utenti/templates/clienti_list.html new file mode 100644 index 0000000..05d2695 --- /dev/null +++ b/utenti/templates/clienti_list.html @@ -0,0 +1,65 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
    +
    +

    Gestione clienti

    + +
    + + +
    +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +
    + + +{% endblock %} \ No newline at end of file diff --git a/utenti/templates/tour_operator_list.html b/utenti/templates/tour_operator_list.html new file mode 100644 index 0000000..79a3890 --- /dev/null +++ b/utenti/templates/tour_operator_list.html @@ -0,0 +1,65 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
    +
    +

    Gestione tour operator

    + +
    +
    +

    Lista tour operator

    + + + +
    + +
    +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +
    + + +{% endblock %} \ No newline at end of file diff --git a/utenti/urls.py b/utenti/urls.py index cb3104e..7a3fd5a 100644 --- a/utenti/urls.py +++ b/utenti/urls.py @@ -3,7 +3,8 @@ from django.contrib import admin from django.contrib.auth import views as auth_views -from utenti.views import Autentication, Logout, Register +from utenti.datatables import UserDatatables +from utenti.views import Autentication, Logout, Register, AdminListView, TourOperatorListView, ClientiListView urlpatterns = [ path('accounts/', include('django.contrib.auth.urls')), @@ -15,4 +16,13 @@ urlpatterns = [ path('reset/done/', auth_views.PasswordResetCompleteView.as_view(template_name='registration/custom_password_reset_complete.html'),name='password_reset_complete'), path('register/', Register.as_view(), name='register'), + ## TEMPLATEVIEWS ## + path('admin_list/', AdminListView.as_view(), name='admin_list'), + path('touroperator_list/', TourOperatorListView.as_view(), name='touroperator_list'), + path('clienti_list/', ClientiListView.as_view(), name='clienti_list'), + + ## DATATABLES ## + path('user_datatables/', UserDatatables.as_view(), name='user_datatables'), + + ] \ No newline at end of file diff --git a/utenti/views.py b/utenti/views.py index 9c22438..7eea356 100644 --- a/utenti/views.py +++ b/utenti/views.py @@ -3,6 +3,7 @@ from django.shortcuts import render, redirect from django.views import View from django.contrib import messages from django.contrib.auth import login, authenticate, logout +from django.views.generic import TemplateView from utenti.forms import FormLogin, RegistrationForm @@ -62,9 +63,26 @@ class Register(View): form.save() return redirect('utenti:login') else: - messages.error(request, 'Please correct form and try again') + errors = '' + for err in form.errors.as_data(): + errors += '
  • ' + err + '
  • ' + + messages.error(request, errors) form = RegistrationForm() + return redirect('utenti:register') + + +class AdminListView(TemplateView): + template_name = 'admin_list.html' + + +class TourOperatorListView(TemplateView): + template_name = 'tour_operator_list.html' + + +class ClientiListView(TemplateView): + template_name = 'clienti_list.html' # from braces.views import GroupRequiredMixin # class SomeProtectedView(GroupRequiredMixin, TemplateView): -- 2.43.0