Feat: Implementierung des Spieler- und Eltern-Verifizierungsprozesses
Fügt einen umfassenden Verifizierungsprozess für neu erstellte Spieler
und zugeordnete Eltern hinzu. Dies ersetzt das frühere Einladungscode-System.
Wesentliche Änderungen:
- **`CustomUser` Modell:** Erweitert um `is_verified` (Standard `False`) und
`verification_code` (UUID) Felder. `is_active` ist nun standardmäßig `False`
bis zur Verifizierung. Das `InvitationCode`-Modell wurde entfernt.
- **E-Mail-Utility (`accounts/utils.py`):** Eine neue Funktion `send_verification_email`
sendet oder simuliert E-Mails (basierend auf `settings.MTP_EMAIL_SEND`).
Simulierte E-Mails werden im `.mbox`-Format in `tmp_mails/` gespeichert.
- **`settings.py`:** `DEFAULT_FROM_EMAIL` wurde hinzugefügt.
- **`PlayerCreateView` (`accounts/views.py`):**
- Generiert `verification_code` für neue Spieler und Eltern.
- Setzt das Passwort für neue Benutzer auf unbrauchbar (`set_unusable_password`).
- Löst den Versand von Verifizierungs-E-Mails aus.
- **`verify_account` View (`accounts/views.py`):**
- Eine neue View, die über einen Link in der E-Mail aufgerufen wird.
- Ermöglicht Spielern, ein Passwort festzulegen.
- Ermöglicht Eltern, einen eindeutigen Benutzernamen und ein Passwort festzulegen.
- Setzt `is_active` und `is_verified` auf `True` und invalidiert den
Verifizierungscode nach erfolgreicher Einrichtung.
- Loggt den Benutzer nach erfolgreicher Verifizierung direkt ein und zeigt
eine Erfolgsmeldung an.
- Behebt ein Problem bei der Bestimmung von Eltern-Benutzern.
- **Formulare (`accounts/forms.py`):** Neue `PlayerVerificationForm` und
`ParentVerificationForm` für den Verifizierungsprozess.
- **E-Mail-Templates:** Neue Text- und HTML-Templates für Spieler- und
Eltern-Verifizierungs-E-Mails (`accounts/templates/accounts/email/`).
- **Verifizierungs-Template:** Neues Template für die Verifizierungsseite
(`accounts/templates/accounts/verify_account.html`).
- **URLs (`accounts/urls.py`):** Entfernung der alten `invitation_code` und
`register` URLs, Hinzufügung der neuen `verify_account` URL.
- **Datenbankmigrationen:** Migrationen für die Änderungen am `CustomUser`-Modell
erstellt und angewendet.
- **Temporäres Verzeichnis:** `tmp_mails/` Verzeichnis für E-Mail-Simulation erstellt.
This commit is contained in:
parent
5cc9b387b9
commit
bc4b8a1e7f
@ -1,18 +1,5 @@
|
||||
from django import forms
|
||||
from .models import InvitationCode, CustomUser
|
||||
|
||||
class InvitationCodeForm(forms.Form):
|
||||
code = forms.CharField(max_length=255, label="Einladungscode")
|
||||
|
||||
def clean_code(self):
|
||||
code = self.cleaned_data.get('code')
|
||||
try:
|
||||
invitation_code = InvitationCode.objects.get(code=code)
|
||||
if not invitation_code.is_valid():
|
||||
raise forms.ValidationError("Dieser Einladungscode ist nicht mehr gültig.")
|
||||
except InvitationCode.DoesNotExist:
|
||||
raise forms.ValidationError("Ungültiger Einladungscode.")
|
||||
return code
|
||||
from .models import CustomUser
|
||||
|
||||
class CustomUserCreationForm(forms.ModelForm):
|
||||
password = forms.CharField(widget=forms.PasswordInput)
|
||||
@ -37,3 +24,22 @@ class PlayerCreationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = CustomUser
|
||||
fields = ('username', 'first_name', 'last_name', 'email', 'birth_date', 'player_number', 'team')
|
||||
|
||||
class PlayerVerificationForm(forms.Form):
|
||||
password = forms.CharField(widget=forms.PasswordInput, label="Passwort")
|
||||
password_confirm = forms.CharField(widget=forms.PasswordInput, label="Passwort bestätigen")
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if cleaned_data.get('password') != cleaned_data.get('password_confirm'):
|
||||
raise forms.ValidationError("Die Passwörter stimmen nicht überein.")
|
||||
return cleaned_data
|
||||
|
||||
class ParentVerificationForm(PlayerVerificationForm):
|
||||
username = forms.CharField(max_length=150, label="Benutzername")
|
||||
|
||||
def clean_username(self):
|
||||
username = self.cleaned_data.get('username')
|
||||
if CustomUser.objects.filter(username=username).exists():
|
||||
raise forms.ValidationError("Dieser Benutzername ist bereits vergeben.")
|
||||
return username
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
# Generated by Django 5.2.6 on 2025-11-23 15:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0004_customuser_parents'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='is_verified',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='verification_code',
|
||||
field=models.UUIDField(blank=True, editable=False, null=True, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='customuser',
|
||||
name='is_active',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='InvitationCode',
|
||||
),
|
||||
]
|
||||
@ -1,3 +1,4 @@
|
||||
import uuid
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
@ -8,6 +9,11 @@ class CustomUser(AbstractUser):
|
||||
player_number = models.IntegerField(default=999)
|
||||
team = models.ForeignKey('clubs.Team', on_delete=models.SET_NULL, null=True, blank=True, related_name='players')
|
||||
parents = models.ManyToManyField('self', symmetrical=False, blank=True, related_name='children')
|
||||
is_verified = models.BooleanField(default=False)
|
||||
verification_code = models.UUIDField(null=True, blank=True, unique=True, editable=False)
|
||||
|
||||
# New users are not active until they verify and set a password
|
||||
is_active = models.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def age(self):
|
||||
@ -16,23 +22,6 @@ class CustomUser(AbstractUser):
|
||||
today = datetime.date.today()
|
||||
return today.year - self.birth_date.year - ((today.month, today.day) < (self.birth_date.month, self.birth_date.day))
|
||||
|
||||
class InvitationCode(models.Model):
|
||||
code = models.CharField(max_length=255, unique=True)
|
||||
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
is_active = models.BooleanField(default=True)
|
||||
|
||||
def is_valid(self):
|
||||
if not self.is_active:
|
||||
return False
|
||||
two_weeks_ago = timezone.now() - datetime.timedelta(weeks=2)
|
||||
if self.created_at < two_weeks_ago:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return self.code
|
||||
|
||||
class AbsencePeriod(models.Model):
|
||||
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='absence_periods')
|
||||
start_date = models.DateField()
|
||||
|
||||
15
accounts/templates/accounts/email/parent_verification.html
Normal file
15
accounts/templates/accounts/email/parent_verification.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Kontoaktivierung - Baseball Organisator</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Hallo,</h2>
|
||||
<p>ein Konto wurde für Sie beim Baseball Organisator erstellt, da Sie als Elternteil für einen Spieler registriert wurden.</p>
|
||||
<p>Bitte klicken Sie auf den folgenden Link, um Ihr Konto zu aktivieren. Sie werden aufgefordert, einen Benutzernamen zu wählen und ein Passwort festzulegen:</p>
|
||||
<p><a href="{{ verification_url }}">Konto jetzt aktivieren</a></p>
|
||||
<p>Ihr Verifizierungscode lautet: <strong>{{ verification_code }}</strong></p>
|
||||
<p>Wenn Sie den Link nicht klicken können, kopieren Sie bitte die folgende URL und fügen Sie sie in die Adresszeile Ihres Browsers ein:<br>{{ verification_url }}</p>
|
||||
<p>Vielen Dank,<br>Ihr Baseball Organisator Team</p>
|
||||
</body>
|
||||
</html>
|
||||
14
accounts/templates/accounts/email/parent_verification.txt
Normal file
14
accounts/templates/accounts/email/parent_verification.txt
Normal file
@ -0,0 +1,14 @@
|
||||
Hallo,
|
||||
|
||||
ein Konto wurde für Sie beim Baseball Organisator erstellt, da Sie als Elternteil für einen Spieler registriert wurden.
|
||||
|
||||
Bitte klicken Sie auf den folgenden Link, um Ihr Konto zu aktivieren. Sie werden aufgefordert, einen Benutzernamen zu wählen und ein Passwort festzulegen:
|
||||
|
||||
{{ verification_url }}
|
||||
|
||||
Ihr Verifizierungscode lautet: {{ verification_code }}
|
||||
|
||||
Wenn Sie den Link nicht klicken können, kopieren Sie ihn bitte und fügen Sie ihn in die Adresszeile Ihres Browsers ein.
|
||||
|
||||
Vielen Dank,
|
||||
Ihr Baseball Organisator Team
|
||||
15
accounts/templates/accounts/email/player_verification.html
Normal file
15
accounts/templates/accounts/email/player_verification.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Willkommen beim Baseball Organisator</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Hallo {{ user.first_name }},</h2>
|
||||
<p>willkommen beim Baseball Organisator!</p>
|
||||
<p>Ein Konto wurde für dich von deinem Coach erstellt. Bitte klicke auf den folgenden Link, um dein Passwort festzulegen und dein Konto zu aktivieren:</p>
|
||||
<p><a href="{{ verification_url }}">Konto jetzt aktivieren</a></p>
|
||||
<p>Dein Verifizierungscode lautet: <strong>{{ verification_code }}</strong></p>
|
||||
<p>Wenn du den Link nicht klicken kannst, kopiere bitte die folgende URL und füge sie in die Adresszeile deines Browsers ein:<br>{{ verification_url }}</p>
|
||||
<p>Vielen Dank,<br>Dein Baseball Organisator Team</p>
|
||||
</body>
|
||||
</html>
|
||||
14
accounts/templates/accounts/email/player_verification.txt
Normal file
14
accounts/templates/accounts/email/player_verification.txt
Normal file
@ -0,0 +1,14 @@
|
||||
Hallo {{ user.first_name }},
|
||||
|
||||
willkommen beim Baseball Organisator!
|
||||
|
||||
Ein Konto wurde für dich von deinem Coach erstellt. Bitte klicke auf den folgenden Link, um dein Passwort festzulegen und dein Konto zu aktivieren:
|
||||
|
||||
{{ verification_url }}
|
||||
|
||||
Dein Verifizierungscode lautet: {{ verification_code }}
|
||||
|
||||
Wenn du den Link nicht klicken kannst, kopiere ihn bitte und füge ihn in die Adresszeile deines Browsers ein.
|
||||
|
||||
Vielen Dank,
|
||||
Dein Baseball Organisator Team
|
||||
51
accounts/templates/accounts/verify_account.html
Normal file
51
accounts/templates/accounts/verify_account.html
Normal file
@ -0,0 +1,51 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>Konto verifizieren</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Bitte legen Sie Ihre Zugangsdaten fest.</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if is_parent %}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.username.id_for_label }}" class="form-label">{{ form.username.label }}</label>
|
||||
{{ form.username }}
|
||||
{% for error in form.username.errors %}
|
||||
<div class="alert alert-danger p-1 mt-1">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.password.id_for_label }}" class="form-label">{{ form.password.label }}</label>
|
||||
{{ form.password }}
|
||||
{% for error in form.password.errors %}
|
||||
<div class="alert alert-danger p-1 mt-1">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.password_confirm.id_for_label }}" class="form-label">{{ form.password_confirm.label }}</label>
|
||||
{{ form.password_confirm }}
|
||||
{% for error in form.password_confirm.errors %}
|
||||
<div class="alert alert-danger p-1 mt-1">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% for error in form.non_field_errors %}
|
||||
<div class="alert alert-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
|
||||
<button type="submit" class="btn btn-primary">Konto aktivieren</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -3,8 +3,7 @@ from . import views
|
||||
from django.contrib.auth import views as auth_views
|
||||
|
||||
urlpatterns = [
|
||||
path('invitation/', views.invitation_code_view, name='invitation_code'),
|
||||
path('register/', views.register_view, name='register'),
|
||||
path('verify/<uuid:verification_code>/', views.verify_account, name='verify_account'),
|
||||
path('login/', views.MyLoginView.as_view(template_name='accounts/login.html'), name='login'),
|
||||
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
|
||||
path('profile/', views.edit_profile, name='edit_profile'),
|
||||
|
||||
74
accounts/utils.py
Normal file
74
accounts/utils.py
Normal file
@ -0,0 +1,74 @@
|
||||
import os
|
||||
from django.conf import settings
|
||||
from django.core.mail import send_mail
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
import uuid
|
||||
|
||||
def send_verification_email(user, request, is_parent=False):
|
||||
"""
|
||||
Sends a verification email to a new user (player or parent).
|
||||
"""
|
||||
# Ensure user has a verification code
|
||||
if not user.verification_code:
|
||||
user.verification_code = uuid.uuid4()
|
||||
user.save()
|
||||
|
||||
# Build the verification URL
|
||||
verification_path = reverse('verify_account', kwargs={'verification_code': str(user.verification_code)})
|
||||
verification_url = request.build_absolute_uri(verification_path)
|
||||
|
||||
# Determine which template and subject to use
|
||||
if is_parent:
|
||||
subject = 'Verifizieren Sie Ihr Eltern-Konto für den Baseball Organisator'
|
||||
template_prefix = 'accounts/email/parent_verification'
|
||||
else:
|
||||
subject = 'Willkommen beim Baseball Organisator! Bitte verifizieren Sie Ihr Konto.'
|
||||
template_prefix = 'accounts/email/player_verification'
|
||||
|
||||
context = {
|
||||
'user': user,
|
||||
'verification_url': verification_url,
|
||||
'verification_code': user.verification_code
|
||||
}
|
||||
|
||||
# Render email body from templates
|
||||
email_body_txt = render_to_string(f'{template_prefix}.txt', context)
|
||||
email_body_html = render_to_string(f'{template_prefix}.html', context)
|
||||
|
||||
# Send or simulate email based on settings
|
||||
if settings.MTP_EMAIL_SEND == 1:
|
||||
send_mail(
|
||||
subject=subject,
|
||||
message=email_body_txt,
|
||||
from_email=settings.DEFAULT_FROM_EMAIL, # Make sure this is set in settings.py
|
||||
recipient_list=[user.email],
|
||||
html_message=email_body_html,
|
||||
fail_silently=False,
|
||||
)
|
||||
else:
|
||||
# Simulate email by saving to a file
|
||||
mbox_content = f"""From: {settings.DEFAULT_FROM_EMAIL}
|
||||
To: {user.email}
|
||||
Subject: {subject}
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary="boundary"
|
||||
|
||||
--boundary
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
{email_body_txt}
|
||||
|
||||
--boundary
|
||||
Content-Type: text/html; charset="utf-8"
|
||||
|
||||
{email_body_html}
|
||||
|
||||
--boundary--
|
||||
"""
|
||||
# Ensure the tmp_mails directory exists
|
||||
os.makedirs('tmp_mails', exist_ok=True)
|
||||
# Save the email to a file
|
||||
file_path = os.path.join('tmp_mails', f'{user.email}_{user.verification_code}.mbox')
|
||||
with open(file_path, 'w') as f:
|
||||
f.write(mbox_content)
|
||||
@ -3,53 +3,15 @@ from django.urls import reverse_lazy
|
||||
from django.views.generic.edit import CreateView
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.contrib.auth import views as auth_views, login
|
||||
from django.contrib import messages
|
||||
from django.db.models import Q
|
||||
from django.http import JsonResponse
|
||||
from .forms import InvitationCodeForm, CustomUserCreationForm, CustomUserChangeForm, PlayerCreationForm
|
||||
from .models import CustomUser, InvitationCode
|
||||
from .forms import CustomUserCreationForm, CustomUserChangeForm, PlayerCreationForm, PlayerVerificationForm, ParentVerificationForm
|
||||
from .models import CustomUser
|
||||
from .utils import send_verification_email
|
||||
import uuid
|
||||
|
||||
def invitation_code_view(request):
|
||||
if request.method == 'POST':
|
||||
form = InvitationCodeForm(request.POST)
|
||||
if form.is_valid():
|
||||
code = form.cleaned_data['code']
|
||||
request.session['invitation_code'] = code
|
||||
return redirect('register')
|
||||
else:
|
||||
form = InvitationCodeForm()
|
||||
return render(request, 'accounts/invitation_code.html', {'form': form})
|
||||
|
||||
def register_view(request):
|
||||
invitation_code_str = request.session.get('invitation_code')
|
||||
if not invitation_code_str:
|
||||
return redirect('invitation_code')
|
||||
|
||||
try:
|
||||
invitation_code = InvitationCode.objects.get(code=invitation_code_str)
|
||||
if not invitation_code.is_valid():
|
||||
# Handle invalid code, maybe redirect with a message
|
||||
return redirect('invitation_code')
|
||||
except InvitationCode.DoesNotExist:
|
||||
return redirect('invitation_code')
|
||||
|
||||
|
||||
if request.method == 'POST':
|
||||
form = CustomUserCreationForm(request.POST)
|
||||
if form.is_valid():
|
||||
user = form.save(commit=False)
|
||||
user.set_password(form.cleaned_data['password'])
|
||||
user.save()
|
||||
invitation_code.is_active = False
|
||||
invitation_code.user = user
|
||||
invitation_code.save()
|
||||
# Log the user in and redirect to the dashboard
|
||||
return redirect('login') # Or wherever you want to redirect after registration
|
||||
else:
|
||||
form = CustomUserCreationForm()
|
||||
return render(request, 'accounts/register.html', {'form': form})
|
||||
|
||||
@login_required
|
||||
def edit_profile(request):
|
||||
if request.method == 'POST':
|
||||
@ -74,11 +36,13 @@ class PlayerCreateView(LoginRequiredMixin, HeadCoachCheckMixin, CreateView):
|
||||
def form_valid(self, form):
|
||||
# Create player user
|
||||
player = form.save(commit=False)
|
||||
player.is_active = False # Player can only login after using invitation code
|
||||
player.is_active = False # Player is inactive until verified
|
||||
player.set_unusable_password() # Password must be set via verification
|
||||
player.verification_code = uuid.uuid4()
|
||||
player.save()
|
||||
|
||||
# Create invitation code for player
|
||||
InvitationCode.objects.create(code=str(uuid.uuid4()), user=player)
|
||||
|
||||
# Send verification email to player
|
||||
send_verification_email(player, self.request, is_parent=False)
|
||||
|
||||
# Handle parents
|
||||
for i in ['1', '2']:
|
||||
@ -96,7 +60,6 @@ class PlayerCreateView(LoginRequiredMixin, HeadCoachCheckMixin, CreateView):
|
||||
except CustomUser.DoesNotExist:
|
||||
form.add_error(f'parent{i}_search', 'User not found.')
|
||||
else:
|
||||
# if no user is selected from the list, maybe the user typed an email/username directly
|
||||
try:
|
||||
parent_user = CustomUser.objects.get(Q(username=search_identifier) | Q(email=search_identifier))
|
||||
player.parents.add(parent_user)
|
||||
@ -106,8 +69,16 @@ class PlayerCreateView(LoginRequiredMixin, HeadCoachCheckMixin, CreateView):
|
||||
form.add_error(f'parent{i}_search', 'Multiple users found. Please be more specific.')
|
||||
|
||||
elif new_email:
|
||||
parent_user, created = CustomUser.objects.get_or_create(email=new_email, defaults={'username': new_email, 'is_active': False})
|
||||
InvitationCode.objects.create(code=str(uuid.uuid4()), user=parent_user)
|
||||
parent_user, created = CustomUser.objects.get_or_create(
|
||||
email=new_email,
|
||||
defaults={'username': new_email, 'is_active': False}
|
||||
)
|
||||
if created:
|
||||
parent_user.set_unusable_password()
|
||||
parent_user.verification_code = uuid.uuid4()
|
||||
parent_user.save()
|
||||
# Send verification email to new parent
|
||||
send_verification_email(parent_user, self.request, is_parent=True)
|
||||
player.parents.add(parent_user)
|
||||
|
||||
if form.errors:
|
||||
@ -127,4 +98,32 @@ def user_search(request):
|
||||
results = []
|
||||
for user in users:
|
||||
results.append(f"{user['last_name']}, {user['first_name']} ({user['username']})")
|
||||
return JsonResponse(results, safe=False)
|
||||
return JsonResponse(results, safe=False)
|
||||
|
||||
def verify_account(request, verification_code):
|
||||
user = get_object_or_404(CustomUser, verification_code=verification_code, is_verified=False)
|
||||
|
||||
# Determine if user is a parent (has no team) or player
|
||||
is_parent = user.team is None
|
||||
|
||||
FormClass = ParentVerificationForm if is_parent else PlayerVerificationForm
|
||||
|
||||
if request.method == 'POST':
|
||||
form = FormClass(request.POST)
|
||||
if form.is_valid():
|
||||
user.set_password(form.cleaned_data['password'])
|
||||
if is_parent:
|
||||
user.username = form.cleaned_data['username']
|
||||
|
||||
user.is_active = True
|
||||
user.is_verified = True
|
||||
user.verification_code = None # Invalidate the code
|
||||
user.save()
|
||||
|
||||
login(request, user) # Log the user in
|
||||
messages.success(request, 'Your account has been verified! You are now logged in.')
|
||||
return redirect('dashboard')
|
||||
else:
|
||||
form = FormClass()
|
||||
|
||||
return render(request, 'accounts/verify_account.html', {'form': form, 'is_parent': is_parent})
|
||||
@ -141,3 +141,6 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
AUTH_USER_MODEL = 'accounts.CustomUser'
|
||||
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
|
||||
MTP_EMAIL_SEND = 0
|
||||
DEFAULT_FROM_EMAIL = 'webmaster@localhost'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user