Merge branch 'master' into kybo
This commit is contained in:
commit
833dac43c0
73 changed files with 831 additions and 11 deletions
30
.github/workflows/django.yml
vendored
Normal file
30
.github/workflows/django.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
name: Django CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master, flifloo, kybo ]
|
||||
pull_request:
|
||||
branches: [ master, flifloo, kybo ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
python-version: [3.7, 3.8, 3.9]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
- name: Run Tests
|
||||
run: |
|
||||
python manage.py test
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -109,3 +109,4 @@ GitHub.sublime-settings
|
|||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history
|
||||
/nuitdelinfo_2021/settings.py
|
||||
|
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
|
@ -0,0 +1,9 @@
|
|||
FROM python:3.9.9-alpine
|
||||
WORKDIR /nuitdelinfo_2021
|
||||
COPY . .
|
||||
RUN apk add --no-cache postgresql-libs && \
|
||||
apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev && \
|
||||
pip install --no-cache-dir -r requirements.txt && \
|
||||
apk --purge del .build-deps
|
||||
RUN cp /nuitdelinfo_2021/nuitdelinfo_2021/settings.py.exemple /nuitdelinfo_2021/nuitdelinfo_2021/settings.py
|
||||
CMD [ "python", "./manage.py", "runserver", "0.0.0.0:8000"]
|
0
crew/__init__.py
Normal file
0
crew/__init__.py
Normal file
3
crew/admin.py
Normal file
3
crew/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
6
crew/apps.py
Normal file
6
crew/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class CrewConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'crew'
|
0
crew/migrations/__init__.py
Normal file
0
crew/migrations/__init__.py
Normal file
10
crew/models.py
Normal file
10
crew/models.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.db.models import Model, CharField, ManyToManyField, TextField
|
||||
|
||||
from nuitdelinfo_2021.models import People
|
||||
|
||||
|
||||
class Crew(Model):
|
||||
name = CharField()
|
||||
members = ManyToManyField(People)
|
||||
|
||||
description = TextField()
|
3
crew/tests.py
Normal file
3
crew/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
7
crew/urls.py
Normal file
7
crew/urls.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('<int:crew_id>', views.index, name='index'),
|
||||
]
|
6
crew/views.py
Normal file
6
crew/views.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.shortcuts import render
|
||||
|
||||
|
||||
def index(request, crew_id: int):
|
||||
context = {}
|
||||
return render(request, "crew.html", context)
|
25
docker-compose.yml
Normal file
25
docker-compose.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
django:
|
||||
container_name: "nuitdelinfo_2021"
|
||||
build: ./
|
||||
image: nuitdelinfo_2021
|
||||
ports:
|
||||
- "8001:8000"
|
||||
volumes:
|
||||
- "django:/nuitdelinfo_2021/"
|
||||
|
||||
postgres:
|
||||
container_name: "nuitdelinfo_2021_db"
|
||||
image: postgres
|
||||
environment:
|
||||
POSTGRES_PASSWORD: nuitdelinfo_2021
|
||||
POSTGRES_USER: nuitdelinfo_2021
|
||||
POSTGRES_DB: nuitdelinfo_2021
|
||||
volumes:
|
||||
- "db:/var/lib/postgresql/data"
|
||||
|
||||
volumes:
|
||||
django:
|
||||
db:
|
0
error/__init__.py
Normal file
0
error/__init__.py
Normal file
3
error/admin.py
Normal file
3
error/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
6
error/apps.py
Normal file
6
error/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ErrorConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'error'
|
21
error/migrations/0001_initial.py
Normal file
21
error/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-02 20:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ThomasPesquetQuotes',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('text', models.TextField()),
|
||||
],
|
||||
),
|
||||
]
|
0
error/migrations/__init__.py
Normal file
0
error/migrations/__init__.py
Normal file
5
error/models.py
Normal file
5
error/models.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
from django.db.models import Model, TextField
|
||||
|
||||
|
||||
class ThomasPesquetQuotes(Model):
|
||||
text = TextField()
|
3
error/tests.py
Normal file
3
error/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
3
error/urls.py
Normal file
3
error/urls.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
22
error/views.py
Normal file
22
error/views.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from django.http import Http404
|
||||
from django.shortcuts import render
|
||||
|
||||
from error.models import ThomasPesquetQuotes
|
||||
|
||||
|
||||
def index(request, exception=None):
|
||||
try:
|
||||
quote = ThomasPesquetQuotes.objects.order_by("?")[0].text
|
||||
except:
|
||||
quote = None
|
||||
|
||||
response = render(request, "error.html", {
|
||||
"quote": quote
|
||||
})
|
||||
|
||||
response.status_code = 500
|
||||
|
||||
if isinstance(exception, Http404):
|
||||
response.status_code = 404
|
||||
|
||||
return response
|
|
@ -1,6 +0,0 @@
|
|||
from django.db.models import Model, CharField, TextField
|
||||
|
||||
|
||||
class Rescue(Model):
|
||||
name = CharField(max_length="256")
|
||||
text = TextField()
|
|
@ -31,12 +31,16 @@ ALLOWED_HOSTS = ["3cab-134-214-214-199.ngrok.io", "localhost", "3218-134-214-214
|
|||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"rescue.apps.RescueConfig",
|
||||
"people.apps.PeopleConfig",
|
||||
"error.apps.ErrorConfig",
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
"django_quill"
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
@ -76,9 +80,12 @@ WSGI_APPLICATION = 'nuitdelinfo_2021.wsgi.application'
|
|||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'HOST': 'localhost',
|
||||
'USER': 'nuitdelinfo_2021',
|
||||
'NAME': 'nuitdelinfo_2021',
|
||||
'PASSWORD': 'nuitdelinfo_2021'
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,3 +135,12 @@ STATICFILES_DIRS = (path.join('static'),)
|
|||
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
ACCOUNT_ACTIVATION_DAYS = 7
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
|
||||
EMAIL_USE_TLS = True
|
||||
EMAIL_HOST = 'smtp.gmail.com'
|
||||
EMAIL_PORT = 587
|
||||
EMAIL_HOST_USER = 'me@gmail.com'
|
||||
EMAIL_HOST_PASSWORD = 'password'
|
|
@ -14,11 +14,19 @@ Including another URLconf
|
|||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.urls import path, include
|
||||
|
||||
from nuitdelinfo_2021 import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.index, name="index"),
|
||||
path("a/", include("rescue.urls")),
|
||||
path("p/", include("people.urls")),
|
||||
path('admin/', admin.site.urls),
|
||||
path('accounts/', include('django_registration.backends.activation.urls')),
|
||||
path('accounts/', include('django.contrib.auth.urls'))
|
||||
]
|
||||
|
||||
handler400 = "error.views.index"
|
||||
handler404 = "error.views.index"
|
||||
handler500 = "error.views.index"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
from .index import index
|
0
people/__init__.py
Normal file
0
people/__init__.py
Normal file
3
people/admin.py
Normal file
3
people/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
6
people/apps.py
Normal file
6
people/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PeopleConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'people'
|
18
people/forms.py
Normal file
18
people/forms.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from django.forms import ModelForm, DateInput
|
||||
|
||||
from people.models import People
|
||||
|
||||
|
||||
class DateInput(DateInput):
|
||||
input_type = "date"
|
||||
|
||||
|
||||
class SubmitPeople(ModelForm):
|
||||
class Meta:
|
||||
model = People
|
||||
fields = ["first_name", "last_name", "title", "description", "birth", "death", "history", "genealogy", "awards",
|
||||
"pro_life", "testimonials", "sources"]
|
||||
widgets = {
|
||||
"birth": DateInput(),
|
||||
"death": DateInput()
|
||||
}
|
32
people/migrations/0001_initial.py
Normal file
32
people/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-02 20:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='People',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('first_name', models.CharField(max_length=40)),
|
||||
('last_name', models.CharField(max_length=60)),
|
||||
('title', models.CharField(max_length=70)),
|
||||
('description', models.TextField()),
|
||||
('birth', models.DateField()),
|
||||
('death', models.DateField()),
|
||||
('history', models.TextField()),
|
||||
('genealogy', models.TextField()),
|
||||
('awards', models.TextField()),
|
||||
('pro_life', models.TextField()),
|
||||
('testimonials', models.TextField()),
|
||||
('sources', models.TextField()),
|
||||
],
|
||||
),
|
||||
]
|
59
people/migrations/0002_auto_20211202_2127.py
Normal file
59
people/migrations/0002_auto_20211202_2127.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-02 21:27
|
||||
|
||||
from django.db import migrations, models
|
||||
import django_quill.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('people', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='awards',
|
||||
field=django_quill.fields.QuillField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='death',
|
||||
field=models.DateField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='description',
|
||||
field=django_quill.fields.QuillField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='genealogy',
|
||||
field=django_quill.fields.QuillField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='history',
|
||||
field=django_quill.fields.QuillField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='pro_life',
|
||||
field=django_quill.fields.QuillField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='sources',
|
||||
field=django_quill.fields.QuillField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='testimonials',
|
||||
field=django_quill.fields.QuillField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='title',
|
||||
field=models.CharField(max_length=70, null=True),
|
||||
),
|
||||
]
|
60
people/migrations/0003_auto_20211202_2225.py
Normal file
60
people/migrations/0003_auto_20211202_2225.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-02 22:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django_quill.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('people', '0002_auto_20211202_2127'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='people',
|
||||
name='pending_edit_of',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='people.people'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='people',
|
||||
name='validated',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='awards',
|
||||
field=django_quill.fields.QuillField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='death',
|
||||
field=models.DateField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='genealogy',
|
||||
field=django_quill.fields.QuillField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='history',
|
||||
field=django_quill.fields.QuillField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='pro_life',
|
||||
field=django_quill.fields.QuillField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='testimonials',
|
||||
field=django_quill.fields.QuillField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='people',
|
||||
name='title',
|
||||
field=models.CharField(blank=True, max_length=70, null=True),
|
||||
),
|
||||
]
|
0
people/migrations/__init__.py
Normal file
0
people/migrations/__init__.py
Normal file
27
people/models.py
Normal file
27
people/models.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from django.db.models import Model, CharField, DateField, BooleanField, ForeignKey, CASCADE
|
||||
from django_quill.fields import QuillField
|
||||
|
||||
|
||||
class People(Model):
|
||||
first_name = CharField(max_length=40)
|
||||
last_name = CharField(max_length=60)
|
||||
|
||||
title = CharField(max_length=70, null=True, blank=True)
|
||||
description = QuillField()
|
||||
|
||||
birth = DateField()
|
||||
death = DateField(null=True, blank=True)
|
||||
|
||||
history = QuillField(null=True, blank=True)
|
||||
genealogy = QuillField(null=True, blank=True)
|
||||
awards = QuillField(null=True, blank=True)
|
||||
pro_life = QuillField(null=True, blank=True)
|
||||
|
||||
testimonials = QuillField(null=True, blank=True)
|
||||
sources = QuillField()
|
||||
|
||||
validated = BooleanField(default=False)
|
||||
pending_edit_of = ForeignKey("self", on_delete=CASCADE, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.first_name} {self.last_name}"
|
3
people/tests.py
Normal file
3
people/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
9
people/urls.py
Normal file
9
people/urls.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path("<int:people_id>/", views.index, name='index'),
|
||||
path("submit/", views.submit, name="submit"),
|
||||
path("edit/<int:people_id>/", views.edit, name="edit")
|
||||
]
|
54
people/views.py
Normal file
54
people/views.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
|
||||
from people.forms import SubmitPeople
|
||||
from people.models import People
|
||||
|
||||
|
||||
def get_people(people_id: int) -> People:
|
||||
try:
|
||||
return People.objects.get(pk=people_id)
|
||||
except People.DoesNotExist:
|
||||
raise Http404("People does not exist")
|
||||
|
||||
|
||||
def index(request, people_id: int):
|
||||
return render(request, "people/people.html", {
|
||||
"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]))
|
||||
else:
|
||||
form = SubmitPeople()
|
||||
|
||||
return render(request, "people/submit.html", {"form": form})
|
||||
|
||||
|
||||
@login_required
|
||||
def edit(request, people_id: int):
|
||||
edited_people = get_people(people_id)
|
||||
if not edited_people.validated:
|
||||
return HttpResponseBadRequest("This entry is not validated, you can't edit it")
|
||||
|
||||
if request.method == "POST":
|
||||
form = SubmitPeople(request.POST)
|
||||
if form.is_valid():
|
||||
people = form.save()
|
||||
people.pending_edit_of = edited_people
|
||||
people.save()
|
||||
|
||||
return HttpResponseRedirect(reverse(index, 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})
|
8
requirements.txt
Normal file
8
requirements.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
asgiref==3.4.1
|
||||
confusable-homoglyphs==3.2.0
|
||||
Django==3.2.9
|
||||
django-quill-editor==0.1.22
|
||||
django-registration==3.2
|
||||
psycopg2==2.9.2
|
||||
pytz==2021.3
|
||||
sqlparse==0.4.2
|
0
rescue/__init__.py
Normal file
0
rescue/__init__.py
Normal file
3
rescue/admin.py
Normal file
3
rescue/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
6
rescue/apps.py
Normal file
6
rescue/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class RescueConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'rescue'
|
17
rescue/forms.py
Normal file
17
rescue/forms.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from django.forms import ModelForm, DateInput
|
||||
|
||||
from rescue.models import Rescue
|
||||
|
||||
|
||||
class DateInput(DateInput):
|
||||
input_type = "date"
|
||||
|
||||
|
||||
class SubmitRescue(ModelForm):
|
||||
class Meta:
|
||||
model = Rescue
|
||||
fields = ["name", "date", "location_long", "location_lat", "resume", "saved", "rescuers", "description",
|
||||
"sources"]
|
||||
widgets = {
|
||||
"date": DateInput()
|
||||
}
|
30
rescue/migrations/0001_initial.py
Normal file
30
rescue/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-02 20:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('people', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Rescue',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=70)),
|
||||
('date', models.DateField()),
|
||||
('location_long', models.DecimalField(decimal_places=6, max_digits=9)),
|
||||
('location_lat', models.DecimalField(decimal_places=6, max_digits=9)),
|
||||
('resume', models.CharField(max_length=125)),
|
||||
('description', models.TextField()),
|
||||
('sources', models.TextField()),
|
||||
('rescuers', models.ManyToManyField(related_name='rescued', to='people.People')),
|
||||
('saved', models.ManyToManyField(related_name='saved', to='people.People')),
|
||||
],
|
||||
),
|
||||
]
|
24
rescue/migrations/0002_auto_20211202_2301.py
Normal file
24
rescue/migrations/0002_auto_20211202_2301.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-02 23:01
|
||||
|
||||
from django.db import migrations
|
||||
import django_quill.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rescue', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='rescue',
|
||||
name='description',
|
||||
field=django_quill.fields.QuillField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rescue',
|
||||
name='sources',
|
||||
field=django_quill.fields.QuillField(),
|
||||
),
|
||||
]
|
0
rescue/migrations/__init__.py
Normal file
0
rescue/migrations/__init__.py
Normal file
21
rescue/models.py
Normal file
21
rescue/models.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from django.db.models import Model, CharField, DateField, ManyToManyField, DecimalField
|
||||
from django_quill.fields import QuillField
|
||||
|
||||
from people.models import People
|
||||
|
||||
|
||||
class Rescue(Model):
|
||||
name = CharField(max_length=70)
|
||||
date = DateField()
|
||||
|
||||
location_long = DecimalField(max_digits=9, decimal_places=6)
|
||||
location_lat = DecimalField(max_digits=9, decimal_places=6)
|
||||
|
||||
resume = CharField(max_length=125)
|
||||
|
||||
saved = ManyToManyField(People, related_name="saved")
|
||||
rescuers = ManyToManyField(People, related_name="rescued")
|
||||
|
||||
description = QuillField()
|
||||
|
||||
sources = QuillField()
|
3
rescue/tests.py
Normal file
3
rescue/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
9
rescue/urls.py
Normal file
9
rescue/urls.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('<int:rescue_id>', views.index, name='index'),
|
||||
path("submit/", views.submit, name="submit"),
|
||||
path("edit/<int:rescue_id>/", views.edit, name="edit")
|
||||
]
|
52
rescue/views.py
Normal file
52
rescue/views.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
|
||||
from rescue.forms import SubmitRescue
|
||||
from rescue.models import Rescue
|
||||
|
||||
|
||||
def get_rescue(rescue_id: int) -> Rescue:
|
||||
try:
|
||||
return Rescue.objects.get(pk=rescue_id)
|
||||
except Rescue.DoesNotExist:
|
||||
raise Http404("Rescue does not exist")
|
||||
|
||||
|
||||
def index(request, rescue_id: int):
|
||||
return render(request, "article/article.html", {"rescue": get_rescue(rescue_id)})
|
||||
|
||||
|
||||
@login_required
|
||||
def submit(request):
|
||||
if request.method == "POST":
|
||||
form = SubmitRescue(request.POST)
|
||||
if form.is_valid():
|
||||
rescue = form.save()
|
||||
return HttpResponseRedirect(reverse(index, args=[rescue.pk]))
|
||||
else:
|
||||
form = SubmitRescue()
|
||||
|
||||
return render(request, "article/submit.html", {"form": form})
|
||||
|
||||
|
||||
@login_required
|
||||
def edit(request, rescue_id: int):
|
||||
edited_rescue = get_rescue(rescue_id)
|
||||
if not edited_rescue.validated:
|
||||
return HttpResponseBadRequest("This entry is not validated, you can't edit it")
|
||||
|
||||
if request.method == "POST":
|
||||
form = SubmitRescue(request.POST)
|
||||
if form.is_valid():
|
||||
rescue = form.save()
|
||||
rescue.pending_edit_of = edited_rescue
|
||||
rescue.save()
|
||||
|
||||
return HttpResponseRedirect(reverse(index, 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})
|
28
templates/article/article.html
Normal file
28
templates/article/article.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
{% if not rescue.validated %}
|
||||
{% if rescue.pending_edit_of %}
|
||||
<h1>This edit is not validated !</h1>
|
||||
{% else %}
|
||||
<h1>This new entry is not validated !</h1>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{{ rescue.name }} <br />
|
||||
{{ rescue.date }} <br />
|
||||
<br />
|
||||
{{ rescue.location_long }} {{ rescue.location_lat }} <br />
|
||||
<br />
|
||||
{{ rescue.resume.html | safe }} <br />
|
||||
{{ rescue.description.html | safe }} <br />
|
||||
<br />
|
||||
{{ rescue.testimonials.html | safe }} <br />
|
||||
{{ rescue.sources.html | safe }}
|
||||
|
||||
<h3>Saved</h3>
|
||||
{% for people in rescue.saved.all %}
|
||||
<a href="/p/{{ people.pk }}">{{ people }}</a>
|
||||
{% endfor %}
|
||||
|
||||
<h3>Rescuers</h3>
|
||||
{% for people in rescue.rescuers.all %}
|
||||
<a href="/p/{{ people.pk }}">{{ people }}</a>
|
||||
{% endfor %}
|
10
templates/article/edit.html
Normal file
10
templates/article/edit.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<head>
|
||||
{{ form.media }}
|
||||
</head>
|
||||
<body>
|
||||
<form action="/a/edit/{{ edit_id }}/" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</body>
|
10
templates/article/submit.html
Normal file
10
templates/article/submit.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<head>
|
||||
{{ form.media }}
|
||||
</head>
|
||||
<body>
|
||||
<form action="/a/submit/" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</body>
|
0
templates/crew.html
Normal file
0
templates/crew.html
Normal file
1
templates/django_registration/activation_complete.html
Normal file
1
templates/django_registration/activation_complete.html
Normal file
|
@ -0,0 +1 @@
|
|||
Activation complete :/
|
2
templates/django_registration/activation_email_body.txt
Normal file
2
templates/django_registration/activation_email_body.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
activation URL: {{site}}/accounts/activate/{{ activation_key }}/
|
||||
The number of days remaining during which the account may be activated: {{ expiration_days }}
|
|
@ -0,0 +1 @@
|
|||
Activation email for {{ user }}
|
1
templates/django_registration/activation_failed.html
Normal file
1
templates/django_registration/activation_failed.html
Normal file
|
@ -0,0 +1 @@
|
|||
Activation failed :/
|
1
templates/django_registration/registration_closed.html
Normal file
1
templates/django_registration/registration_closed.html
Normal file
|
@ -0,0 +1 @@
|
|||
Registration closed :/
|
1
templates/django_registration/registration_complete.html
Normal file
1
templates/django_registration/registration_complete.html
Normal file
|
@ -0,0 +1 @@
|
|||
Registration complete !
|
5
templates/django_registration/registration_form.html
Normal file
5
templates/django_registration/registration_form.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="login" />
|
||||
</form>
|
6
templates/error.html
Normal file
6
templates/error.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<h1>Oups, une erreur est survenue :/</h1>
|
||||
|
||||
{% if quote %}
|
||||
<h2>Pour nous faire pardonner voici une citation de Thomas Pesquet:</h2>
|
||||
<p>{{ quote }}</p>
|
||||
{% endif %}
|
10
templates/people/edit.html
Normal file
10
templates/people/edit.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<head>
|
||||
{{ form.media }}
|
||||
</head>
|
||||
<body>
|
||||
<form action="/p/edit/{{ edit_id }}/" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</body>
|
23
templates/people/people.html
Normal file
23
templates/people/people.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% if not people.validated %}
|
||||
{% if people.pending_edit_of %}
|
||||
<h1>This edit is not validated !</h1>
|
||||
{% else %}
|
||||
<h1>This new entry is not validated !</h1>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{{ people.first_name }} {{ people.last_name }} <br />
|
||||
{{ people.title }} <br />
|
||||
<br />
|
||||
{{ people.description.html | safe }} <br />
|
||||
<br />
|
||||
{{ people.birth }} <br />
|
||||
{{ people.death }} <br />
|
||||
<br />
|
||||
{{ people.history.html | safe }} <br />
|
||||
{{ people.genealogy.html | safe }} <br />
|
||||
{{ people.awards.html | safe }} <br />
|
||||
{{ people.pro_life.html | safe }} <br />
|
||||
<br />
|
||||
{{ people.testimonials.html | safe }} <br />
|
||||
{{ people.sources.html | safe }}
|
10
templates/people/submit.html
Normal file
10
templates/people/submit.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<head>
|
||||
{{ form.media }}
|
||||
</head>
|
||||
<body>
|
||||
<form action="/p/submit/" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</body>
|
4
templates/registration/logged_out.html
Normal file
4
templates/registration/logged_out.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
{% block content %}
|
||||
<p>Logged out!</p>
|
||||
<a href="{% url 'login'%}">Click here to login again.</a>
|
||||
{% endblock %}
|
37
templates/registration/login.html
Normal file
37
templates/registration/login.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
{% block content %}
|
||||
|
||||
{% if form.errors %}
|
||||
<p>Your username and password didn't match. Please try again.</p>
|
||||
{% endif %}
|
||||
|
||||
{% if next %}
|
||||
{% if user.is_authenticated %}
|
||||
<p>Your account doesn't have access to this page. To proceed,
|
||||
please login with an account that has access.</p>
|
||||
{% else %}
|
||||
<p>Please login to see this page.</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{% url 'login' %}">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ form.username.label_tag }}</td>
|
||||
<td>{{ form.username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ form.password.label_tag }}</td>
|
||||
<td>{{ form.password }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="submit" value="login" />
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
</form>
|
||||
|
||||
{# Assumes you setup the password_reset view in your URLconf #}
|
||||
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>
|
||||
|
||||
<p><a href="{% url 'django_registration_register' %}">Register</a></p>
|
||||
|
||||
{% endblock %}
|
4
templates/registration/password_reset_complete.html
Normal file
4
templates/registration/password_reset_complete.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
{% block content %}
|
||||
<h1>The password has been changed!</h1>
|
||||
<p><a href="{% url 'login' %}">log in again?</a></p>
|
||||
{% endblock %}
|
27
templates/registration/password_reset_confirm.html
Normal file
27
templates/registration/password_reset_confirm.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
{% block content %}
|
||||
{% if validlink %}
|
||||
<p>Please enter (and confirm) your new password.</p>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ form.new_password1.errors }}
|
||||
<label for="id_new_password1">New password:</label></td>
|
||||
<td>{{ form.new_password1 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ form.new_password2.errors }}
|
||||
<label for="id_new_password2">Confirm password:</label></td>
|
||||
<td>{{ form.new_password2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><input type="submit" value="Change my password" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{% else %}
|
||||
<h1>Password reset failed</h1>
|
||||
<p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
3
templates/registration/password_reset_done.html
Normal file
3
templates/registration/password_reset_done.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
{% block content %}
|
||||
<p>We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.</p>
|
||||
{% endblock %}
|
2
templates/registration/password_reset_email.html
Normal file
2
templates/registration/password_reset_email.html
Normal file
|
@ -0,0 +1,2 @@
|
|||
Someone asked for password reset for email {{ email }}. Follow the link below:
|
||||
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
|
10
templates/registration/password_reset_form.html
Normal file
10
templates/registration/password_reset_form.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% block content %}
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% if form.email.errors %}
|
||||
{{ form.email.errors }}
|
||||
{% endif %}
|
||||
<p>{{ form.email }}</p>
|
||||
<input type="submit" class="btn btn-default btn-lg" value="Reset password">
|
||||
</form>
|
||||
{% endblock %}
|
Loading…
Reference in a new issue