diff --git a/boat/__init__.py b/boat/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/boat/admin.py b/boat/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/boat/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/boat/apps.py b/boat/apps.py new file mode 100644 index 0000000..d015290 --- /dev/null +++ b/boat/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BoatConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'boat' diff --git a/boat/forms.py b/boat/forms.py new file mode 100644 index 0000000..f4254a8 --- /dev/null +++ b/boat/forms.py @@ -0,0 +1,13 @@ +from django.forms import ModelForm, DateInput + +from boat.models import Boat + + +class DateInput(DateInput): + input_type = "date" + + +class SubmitBoat(ModelForm): + class Meta: + model = Boat + fields = ["name", "model", "description"] diff --git a/boat/migrations/__init__.py b/boat/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/boat/models.py b/boat/models.py new file mode 100644 index 0000000..0921c87 --- /dev/null +++ b/boat/models.py @@ -0,0 +1,17 @@ +from django.db.models import Model, CharField, BooleanField, ForeignKey, CASCADE +from django_quill.fields import QuillField + +from people.models import People + + +class Boat(Model): + name = CharField(max_length=80) + model = CharField(max_length=80) + + description = QuillField() + + validated = BooleanField(default=False) + pending_edit_of = ForeignKey(People, on_delete=CASCADE, null=True, blank=True) + + def __str__(self): + return self.name diff --git a/boat/tests.py b/boat/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/boat/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/boat/urls.py b/boat/urls.py new file mode 100644 index 0000000..a35eaa2 --- /dev/null +++ b/boat/urls.py @@ -0,0 +1,11 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.index, name='index'), + path("/", views.details, name='details'), + path("submit/", views.submit, name="submit"), + path("edit//", views.edit, name="edit"), + path("ajax/search//", views.ajax_search, name="ajax_search") +] diff --git a/boat/views.py b/boat/views.py new file mode 100644 index 0000000..bb6ef29 --- /dev/null +++ b/boat/views.py @@ -0,0 +1,65 @@ +from django.contrib.auth.decorators import login_required +from django.db.models import Q +from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest, JsonResponse +from django.shortcuts import render +from django.urls import reverse + +from boat.forms import SubmitBoat +from boat.models import Boat + + +def get_boat(boat_id: int) -> Boat: + try: + return Boat.objects.get(pk=boat_id) + except Boat.DoesNotExist: + raise Http404("Boat does not exist") + + +def index(request): + return render(request, "boat/boats.html", { + "boats": Boat.objects.all() + }) + + +def details(request, boat_id: int): + return render(request, "boat/boat.html", { + "boat": get_boat(boat_id) + }) + + +@login_required +def submit(request): + if request.method == "POST": + form = SubmitBoat(request.POST) + if form.is_valid(): + boat = form.save() + return HttpResponseRedirect(reverse(details, args=[boat.pk])) + else: + form = SubmitBoat() + + return render(request, "boat/submit.html", {"form": form}) + + +@login_required +def edit(request, boat_id: int): + edited_boat = get_boat(boat_id) + if not edited_boat.validated: + return HttpResponseBadRequest("This entry is not validated, you can't edit it") + + if request.method == "POST": + form = SubmitBoat(request.POST) + if form.is_valid(): + boat = form.save() + boat.pending_edit_of = edited_boat + boat.save() + + return HttpResponseRedirect(reverse(details, args=[boat.pk])) + else: + edited_boat.pk = None + form = SubmitBoat(instance=edited_boat) + + return render(request, "boat/edit.html", {"form": form, "edit_id": boat_id}) + + +def ajax_search(request, text: str): + return JsonResponse(Boat.objects.filter(Q(name__icontains=text) | Q(description__icontains=text))) diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/admin.py b/core/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/core/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/core/apps.py b/core/apps.py new file mode 100644 index 0000000..8115ae6 --- /dev/null +++ b/core/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'core' diff --git a/core/migrations/__init__.py b/core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/models.py b/core/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/core/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/core/templatetags/__init__.py b/core/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/templatetags/md5.py b/core/templatetags/md5.py new file mode 100644 index 0000000..dab2938 --- /dev/null +++ b/core/templatetags/md5.py @@ -0,0 +1,9 @@ +from django import template +import hashlib + +register = template.Library() + + +@register.filter(name='md5') +def md5_string(value: str): + return hashlib.md5(value.encode()).hexdigest() diff --git a/core/tests.py b/core/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/core/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/core/views.py b/core/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/core/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/crew/admin.py b/crew/admin.py index 8c38f3f..0cce81d 100644 --- a/crew/admin.py +++ b/crew/admin.py @@ -1,3 +1,6 @@ from django.contrib import admin -# Register your models here. +from crew.models import Crew + + +admin.site.register(Crew) diff --git a/crew/models.py b/crew/models.py index c5f6578..8bff808 100644 --- a/crew/models.py +++ b/crew/models.py @@ -8,3 +8,6 @@ class Crew(Model): members = ManyToManyField(People) description = TextField() + + def __str__(self): + return self.name diff --git a/error/admin.py b/error/admin.py index 8c38f3f..29df94f 100644 --- a/error/admin.py +++ b/error/admin.py @@ -1,3 +1,6 @@ from django.contrib import admin -# Register your models here. +from error.models import ThomasPesquetQuotes + + +admin.site.register(ThomasPesquetQuotes) diff --git a/error/models.py b/error/models.py index 2d34d62..cfe505b 100644 --- a/error/models.py +++ b/error/models.py @@ -3,3 +3,6 @@ from django.db.models import Model, TextField class ThomasPesquetQuotes(Model): text = TextField() + + def __str__(self): + return self.text diff --git a/nuitdelinfo_2021/forms.py b/nuitdelinfo_2021/forms.py new file mode 100644 index 0000000..0275344 --- /dev/null +++ b/nuitdelinfo_2021/forms.py @@ -0,0 +1,12 @@ +from django.forms import TextInput, PasswordInput +from django_registration.forms import RegistrationForm + + +class MyCustomUserForm(RegistrationForm): + class Meta(RegistrationForm.Meta): + widgets = { + "username": TextInput(attrs={'placeholder': "Nom d'utilisateur"}), + "email": TextInput(attrs={'placeholder': "Email"}), + "password1": PasswordInput(attrs={'placeholder': "Mot de passe"}), + "password2": PasswordInput(attrs={'placeholder': "Confirmation du mot de passe"}), + } diff --git a/nuitdelinfo_2021/settings.py.exemple b/nuitdelinfo_2021/settings.py.exemple index 2cafeae..2ed6653 100644 --- a/nuitdelinfo_2021/settings.py.exemple +++ b/nuitdelinfo_2021/settings.py.exemple @@ -31,8 +31,10 @@ ALLOWED_HOSTS = ["3cab-134-214-214-199.ngrok.io", "localhost", "4125-134-214-214 # Application definition INSTALLED_APPS = [ + "core.apps.AppConfig", "rescue.apps.RescueConfig", "people.apps.PeopleConfig", + "boat.apps.BoatConfig", "error.apps.ErrorConfig", 'django.contrib.admin', 'django.contrib.auth', diff --git a/nuitdelinfo_2021/urls.py b/nuitdelinfo_2021/urls.py index 6286e2e..65a41b9 100644 --- a/nuitdelinfo_2021/urls.py +++ b/nuitdelinfo_2021/urls.py @@ -15,14 +15,23 @@ Including another URLconf """ from django.contrib import admin from django.urls import path, include +from django_registration.views import RegistrationView from nuitdelinfo_2021 import views +from nuitdelinfo_2021.forms import MyCustomUserForm urlpatterns = [ path('', views.index, name="index"), - path("a/", include("rescue.urls")), - path("p/", include("people.urls")), + path("a/", include("rescue.urls"), name="rescue"), + path("p/", include("people.urls"), name="people"), + path("b/", include("boat.urls"), name="boat"), path('admin/', admin.site.urls), + path('accounts/register/', + RegistrationView.as_view( + form_class=MyCustomUserForm + ), + name='django_registration_register', + ), path('accounts/', include('django_registration.backends.activation.urls')), path('accounts/', include('django.contrib.auth.urls')) ] diff --git a/nuitdelinfo_2021/views.py b/nuitdelinfo_2021/views.py index b49be7a..be7c5de 100644 --- a/nuitdelinfo_2021/views.py +++ b/nuitdelinfo_2021/views.py @@ -1,6 +1,9 @@ from django.shortcuts import render +from rescue.models import Rescue + def index(request): - context = {} - return render(request, "index.html", context) + return render(request, "index.html", { + "rescues": Rescue.objects.order_by("date")[:3] + }) diff --git a/people/admin.py b/people/admin.py index 8c38f3f..695f420 100644 --- a/people/admin.py +++ b/people/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin -# Register your models here. +from people.models import People + +admin.site.register(People) diff --git a/people/urls.py b/people/urls.py index 0a07d07..dca8088 100644 --- a/people/urls.py +++ b/people/urls.py @@ -6,5 +6,6 @@ urlpatterns = [ path("", views.index, name='index'), path("/", views.details, name='details'), path("submit/", views.submit, name="submit"), - path("edit//", views.edit, name="edit") + path("edit//", views.edit, name="edit"), + path("ajax/search//", views.ajax_search, name="ajax_search") ] diff --git a/people/views.py b/people/views.py index 5687eab..36c7b6e 100644 --- a/people/views.py +++ b/people/views.py @@ -1,5 +1,6 @@ from django.contrib.auth.decorators import login_required -from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest +from django.db.models import Q +from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest, JsonResponse from django.shortcuts import render from django.urls import reverse @@ -25,13 +26,14 @@ def details(request, people_id: int): "people": get_people(people_id) }) + @login_required def submit(request): if request.method == "POST": form = SubmitPeople(request.POST) if form.is_valid(): people = form.save() - return HttpResponseRedirect(reverse(index, args=[people.pk])) + return HttpResponseRedirect(reverse(details, args=[people.pk])) else: form = SubmitPeople() @@ -51,9 +53,13 @@ def edit(request, people_id: int): people.pending_edit_of = edited_people people.save() - return HttpResponseRedirect(reverse(index, args=[people.pk])) + return HttpResponseRedirect(reverse(details, args=[people.pk])) else: edited_people.pk = None form = SubmitPeople(instance=edited_people) return render(request, "people/edit.html", {"form": form, "edit_id": people_id}) + + +def ajax_search(request, text: str): + return JsonResponse(People.objects.filter(Q(first_name__icontains=text) | Q(first_name__icontains=text))) diff --git a/rescue/admin.py b/rescue/admin.py index 8c38f3f..a091270 100644 --- a/rescue/admin.py +++ b/rescue/admin.py @@ -1,3 +1,6 @@ from django.contrib import admin -# Register your models here. +from rescue.models import Rescue + + +admin.site.register(Rescue) diff --git a/rescue/forms.py b/rescue/forms.py index 3646b6a..f6089a2 100644 --- a/rescue/forms.py +++ b/rescue/forms.py @@ -10,7 +10,7 @@ class DateInput(DateInput): class SubmitRescue(ModelForm): class Meta: model = Rescue - fields = ["name", "date", "location_long", "location_lat", "resume", "saved", "rescuers", "description", + fields = ["name", "date", "location_long", "location_lat", "resume", "saved", "rescuers", "boats", "description", "sources"] widgets = { "date": DateInput() diff --git a/rescue/models.py b/rescue/models.py index 5089e3b..ee991d9 100644 --- a/rescue/models.py +++ b/rescue/models.py @@ -1,6 +1,8 @@ -from django.db.models import Model, CharField, DateField, ManyToManyField, DecimalField +from django.db.models import Model, CharField, DateField, ManyToManyField, DecimalField, BooleanField, ForeignKey, \ + CASCADE from django_quill.fields import QuillField +from boat.models import Boat from people.models import People @@ -15,7 +17,14 @@ class Rescue(Model): saved = ManyToManyField(People, related_name="saved") rescuers = ManyToManyField(People, related_name="rescued") + boats = ManyToManyField(Boat) + + validated = BooleanField(default=False) + pending_edit_of = ForeignKey(People, on_delete=CASCADE, null=True, blank=True) description = QuillField() sources = QuillField() + + def __str__(self): + return self.name diff --git a/rescue/urls.py b/rescue/urls.py index 42a7fe9..79ba399 100644 --- a/rescue/urls.py +++ b/rescue/urls.py @@ -6,5 +6,6 @@ urlpatterns = [ path('', views.index, name='index'), path('/', views.details, name='details'), path("submit/", views.submit, name="submit"), - path("edit//", views.edit, name="edit") + path("edit//", views.edit, name="edit"), + path("ajax/search//", views.ajax_search, name="ajax_search") ] diff --git a/rescue/views.py b/rescue/views.py index 9e05b8f..8e26770 100644 --- a/rescue/views.py +++ b/rescue/views.py @@ -1,5 +1,6 @@ from django.contrib.auth.decorators import login_required -from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest +from django.db.models import Q +from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest, JsonResponse from django.shortcuts import render from django.urls import reverse @@ -28,7 +29,7 @@ def submit(request): form = SubmitRescue(request.POST) if form.is_valid(): rescue = form.save() - return HttpResponseRedirect(reverse(index, args=[rescue.pk])) + return HttpResponseRedirect(reverse(details, args=[rescue.pk])) else: form = SubmitRescue() @@ -48,9 +49,13 @@ def edit(request, rescue_id: int): rescue.pending_edit_of = edited_rescue rescue.save() - return HttpResponseRedirect(reverse(index, args=[rescue.pk])) + return HttpResponseRedirect(reverse(details, args=[rescue.pk])) else: edited_rescue.pk = None form = SubmitRescue(instance=edited_rescue) return render(request, "article/edit.html", {"form": form, "edit_id": edited_rescue}) + + +def ajax_search(request, text: str): + return JsonResponse(Rescue.objects.filter(Q(name__icontains=text) | Q(date__icontains=text) | Q(resume__icontains=text))) diff --git a/templates/base.html b/templates/base.html index c4f7873..c7a66a4 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,4 +1,5 @@ {% load static %} +{% load md5 %} @@ -14,13 +15,17 @@ -
- search - -
+
+ search + {% if user.is_authenticated %} + + {% else %} + Login + {% endif %} +
@@ -28,4 +33,3 @@ {% endblock %}
- diff --git a/templates/boat/boat.html b/templates/boat/boat.html new file mode 100644 index 0000000..02ff03f --- /dev/null +++ b/templates/boat/boat.html @@ -0,0 +1,17 @@ +{% if not rescue.validated %} + {% if rescue.pending_edit_of %} +

This edit is not validated !

+ {% else %} +

This new entry is not validated !

+ {% endif %} +{% endif %} + +{{ boat.name }}
+{{ boat.model }}
+
+{{ boat.description.html | safe }}
+ +

Rescues

+{% for rescue in rescues.all %} + {{ rescue }} +{% endfor %} diff --git a/templates/boat/boats.html b/templates/boat/boats.html new file mode 100644 index 0000000..d81bb5e --- /dev/null +++ b/templates/boat/boats.html @@ -0,0 +1,25 @@ +{% extends 'base.html' %} +{% load static %} +{% block content %} +
+

Bateaux

+
+ {% for boat in boats %} +
+
+
+ +
+
+

{{ boat.name }}

+ Voir le bateau +
+
+ +
+ {% endfor %} +
+ Charger plus de bateaux +
+ {% include 'quicksearch.html' %} +{% endblock %} \ No newline at end of file diff --git a/templates/boat/edit.html b/templates/boat/edit.html new file mode 100644 index 0000000..493a533 --- /dev/null +++ b/templates/boat/edit.html @@ -0,0 +1,10 @@ + + {{ form.media }} + + +
+ {% csrf_token %} + {{ form }} + +
+ diff --git a/templates/boat/submit.html b/templates/boat/submit.html new file mode 100644 index 0000000..8b0a4ec --- /dev/null +++ b/templates/boat/submit.html @@ -0,0 +1,10 @@ + + {{ form.media }} + + +
+ {% csrf_token %} + {{ form }} + +
+ diff --git a/templates/django_registration/registration_form.html b/templates/django_registration/registration_form.html index 19e304b..6826858 100644 --- a/templates/django_registration/registration_form.html +++ b/templates/django_registration/registration_form.html @@ -1,5 +1,20 @@ -
- {% csrf_token %} - {{ form }} - -
+{% load static %} + + + + + + + + +
+

S'inscrire

+
+
+ {% csrf_token %} + {{ form }} + +
+
+
+ diff --git a/templates/index.html b/templates/index.html index 797480b..b09c0e4 100644 --- a/templates/index.html +++ b/templates/index.html @@ -10,42 +10,20 @@

Articles récents

-
-
-
- + {% for rescue in rescues %} +
+
+
+ +
+
+

{{ rescue.date }}

+

{{ rescue.name }}

+ Voir l'article +
+
-
-

16/02/2020

-

Sauvetage risqué en côte d'Ivoire

- Voir l'article -
-
-
-
-
-
- -
-
-

16/02/2020

-

Sauvetage risqué en côte d'Ivoire

- Voir l'article -
-
-
-
-
-
- -
-
-

16/02/2020

-

Sauvetage risqué en côte d'Ivoire

- Voir l'article -
-
-
+ {% endfor %}
diff --git a/templates/login.html b/templates/login.html deleted file mode 100644 index a9be995..0000000 --- a/templates/login.html +++ /dev/null @@ -1,19 +0,0 @@ -{% load static %} - - - - - - - - -
-

Se connecter

-
- - - -
-
- - diff --git a/templates/register.html b/templates/register.html deleted file mode 100644 index 54346a1..0000000 --- a/templates/register.html +++ /dev/null @@ -1,24 +0,0 @@ -{% load static %} - - - - - - - - -
-

S'inscrire

-
-
- - -
- - - - -
-
- - diff --git a/templates/registration/logged_out.html b/templates/registration/logged_out.html index 61badb0..d31cc31 100644 --- a/templates/registration/logged_out.html +++ b/templates/registration/logged_out.html @@ -1,4 +1,4 @@ {% block content %}

Logged out!

- Click here to login again. + Click here to go home. {% endblock %} diff --git a/templates/registration/login.html b/templates/registration/login.html index 73fd22d..e9aa140 100644 --- a/templates/registration/login.html +++ b/templates/registration/login.html @@ -1,37 +1,36 @@ -{% block content %} +{% load static %} - {% if form.errors %} -

Your username and password didn't match. Please try again.

- {% endif %} + + + + + + +
{% if next %} {% if user.is_authenticated %} -

Your account doesn't have access to this page. To proceed, - please login with an account that has access.

+

Votre compte n'a pas accès à cette page. Pour continuer, veuillez vous connecter avec un compte qui a accès.

{% else %} -

Please login to see this page.

+

Veuillez vous connecter pour voir cette page.

{% endif %} {% endif %} -
- {% csrf_token %} - - - - - - - - - -
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
- - -
+

Se connecter

+ {% if form.errors %} +

Votre nom d'utilisateur et votre mot de passe ne correspondent pas. Veuillez réessayer.

+ {% endif %} +
+
+ {% csrf_token %} + + + + +
+
- {# Assumes you setup the password_reset view in your URLconf #}

Lost password?

Register

- -{% endblock %} +