Merge branch 'kybo' of github.com:flifloo/nuitdelinfo_2021 into kybo

This commit is contained in:
Kybo09 2021-12-03 02:15:44 +01:00
commit aa48208d29
73 changed files with 831 additions and 11 deletions

30
.github/workflows/django.yml vendored Normal file
View 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
View file

@ -109,3 +109,4 @@ GitHub.sublime-settings
!.vscode/launch.json
!.vscode/extensions.json
.history
/nuitdelinfo_2021/settings.py

9
Dockerfile Normal file
View 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
View file

3
crew/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
crew/apps.py Normal file
View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class CrewConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'crew'

View file

10
crew/models.py Normal file
View 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
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

7
crew/urls.py Normal file
View 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
View 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
View 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
View file

3
error/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
error/apps.py Normal file
View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ErrorConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'error'

View 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()),
],
),
]

View file

5
error/models.py Normal file
View file

@ -0,0 +1,5 @@
from django.db.models import Model, TextField
class ThomasPesquetQuotes(Model):
text = TextField()

3
error/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
error/urls.py Normal file
View file

@ -0,0 +1,3 @@
from django.urls import path
from . import views

22
error/views.py Normal file
View 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

View file

@ -1,6 +0,0 @@
from django.db.models import Model, CharField, TextField
class Rescue(Model):
name = CharField(max_length="256")
text = TextField()

View file

@ -31,12 +31,16 @@ ALLOWED_HOSTS = ["3cab-134-214-214-199.ngrok.io", "localhost", "4125-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'

View file

@ -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"

View file

@ -1 +0,0 @@
from .index import index

0
people/__init__.py Normal file
View file

3
people/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
people/apps.py Normal file
View 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
View 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()
}

View 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()),
],
),
]

View 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),
),
]

View 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),
),
]

View file

27
people/models.py Normal file
View 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
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
people/urls.py Normal file
View 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
View 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
View 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
View file

3
rescue/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
rescue/apps.py Normal file
View 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
View 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()
}

View 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')),
],
),
]

View 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(),
),
]

View file

21
rescue/models.py Normal file
View 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
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
rescue/urls.py Normal file
View 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
View 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})

View 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 %}

View 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>

View 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
View file

View file

@ -0,0 +1 @@
Activation complete :/

View 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 }}

View file

@ -0,0 +1 @@
Activation email for {{ user }}

View file

@ -0,0 +1 @@
Activation failed :/

View file

@ -0,0 +1 @@
Registration closed :/

View file

@ -0,0 +1 @@
Registration complete !

View file

@ -0,0 +1,5 @@
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="login" />
</form>

6
templates/error.html Normal file
View 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 %}

View 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>

View 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 }}

View 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>

View file

@ -0,0 +1,4 @@
{% block content %}
<p>Logged out!</p>
<a href="{% url 'login'%}">Click here to login again.</a>
{% endblock %}

View 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 %}

View 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 %}

View 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 %}

View 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 %}

View 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 %}

View 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 %}