mirror of
https://github.com/Sosokker/ku-polls.git
synced 2025-12-18 21:14:05 +01:00
Add User+Authenticate(login,logout,reset password)
Also add view for signup page + custom form for signup
This commit is contained in:
parent
d6fd968ea4
commit
01ea565859
@ -126,3 +126,9 @@ STATICFILES_DIRS = [BASE_DIR]
|
|||||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
LOGIN_REDIRECT_URL = "home_redirect"
|
||||||
|
LOGOUT_REDIRECT_URL = "home_redirect"
|
||||||
|
|
||||||
|
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
|
||||||
|
EMAIL_FILE_PATH = BASE_DIR / "sent_emails"
|
||||||
@ -7,4 +7,5 @@ urlpatterns = [
|
|||||||
path('', RedirectView.as_view(pattern_name='polls:index'), name='home_redirect'),
|
path('', RedirectView.as_view(pattern_name='polls:index'), name='home_redirect'),
|
||||||
path("polls/", include("polls.urls")),
|
path("polls/", include("polls.urls")),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
path("accounts/", include("django.contrib.auth.urls")),
|
||||||
]
|
]
|
||||||
|
|||||||
27
polls/forms.py
Normal file
27
polls/forms.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from django import forms
|
||||||
|
from django.contrib.auth.forms import UserCreationForm
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class SignUpForm(UserCreationForm):
|
||||||
|
tailwind_class = "w-full border-2 border-gray-300 bg-gray-100 rounded-lg focus:ring focus:border-blue-300 focus:shadow-none"
|
||||||
|
|
||||||
|
username = forms.CharField(widget=forms.TextInput(attrs={'class': tailwind_class}),
|
||||||
|
error_messages={
|
||||||
|
'unique': 'This username is already in use.',
|
||||||
|
'invalid': 'Invalid username format.',
|
||||||
|
'max_length': 'Username should not exceed 150 characters.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
password1 = forms.CharField(widget=forms.PasswordInput(attrs={'class': tailwind_class}),
|
||||||
|
error_messages={'min_length': 'Password must contain at least 8 characters.',}
|
||||||
|
)
|
||||||
|
password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class': tailwind_class}),)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ('username', 'password1', 'password2')
|
||||||
|
|
||||||
|
error_messages = {
|
||||||
|
'password_mismatch': "The two password fields didn't match.",
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@ from django.utils import timezone
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
class Question(models.Model):
|
class Question(models.Model):
|
||||||
|
|||||||
@ -26,15 +26,22 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<!--End-->
|
<!--End-->
|
||||||
<button class="flex items-center whitespace-nowrap rounded-full border border-transparent bg-green-500 px-5 py-2 text-sm font-bold text-white transition duration-150 ease-in-out hover:scale-[101%] hover:bg-green-700 focus:bg-green-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 active:bg-green-900">
|
|
||||||
New Poll
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<a href=""
|
{% if user.is_authenticated %}
|
||||||
class="flex items-center whitespace-nowrap rounded-full border border-transparent bg-neutral-800 px-5 py-2 text-sm font-bold text-white transition duration-150 ease-in-out hover:scale-[101%] hover:bg-neutral-700 focus:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 active:bg-neutral-900">
|
<button class="flex items-center whitespace-nowrap rounded-full border border-transparent bg-green-500 px-5 py-2 text-sm font-bold text-white transition duration-150 ease-in-out hover:scale-[101%] hover:bg-green-700 focus:bg-green-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 active:bg-green-900">
|
||||||
|
New Poll
|
||||||
|
</button>
|
||||||
|
<a href="{% url 'logout' %}"
|
||||||
|
class="flex items-center whitespace-nowrap rounded-full border border-transparent bg-red-600 px-5 py-2 text-sm font-bold text-white transition duration-150 ease-in-out hover:scale-[101%] hover:bg-red-700 focus:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 active:bg-neutral-900">
|
||||||
|
<span>Sign out <span class="hidden sm:inline-block">😭</span></span>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'login' %}"
|
||||||
|
class="flex items-center whitespace-nowrap rounded-full border border-transparent bg-neutral-800 px-5 py-2 text-sm font-bold text-white transition duration-150 ease-in-out hover:scale-[101%] hover:bg-neutral-700 focus:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 active:bg-red-900">
|
||||||
<span>Sign in <span class="hidden sm:inline-block">😎</span></span>
|
<span>Sign in <span class="hidden sm:inline-block">😎</span></span>
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
37
polls/templates/registration/login.html
Normal file
37
polls/templates/registration/login.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Sign In Page</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-gray-100 min-h-screen flex items-center justify-center">
|
||||||
|
<div class="bg-white p-8 shadow-md rounded-md w-96">
|
||||||
|
<h2 class="text-3xl font-semibold text-center mb-6">Sign In</h2>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-6 flex flex-col">
|
||||||
|
<p class="block text-gray-700 font-medium mb-2">Username</p>
|
||||||
|
{{ form.username }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-6 flex flex-col">
|
||||||
|
<p class="block text-gray-700 font-medium mb-2">Password</p>
|
||||||
|
{{ form.password }}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="w-full bg-blue-500 text-white py-2 rounded-md hover:bg-blue-600 focus:ring-2 focus:ring-blue-300 focus:outline-none">
|
||||||
|
Log In
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<p class="text-center mt-4 text-gray-600 text-sm">
|
||||||
|
Don't have an account? <a href="{% url 'polls:signup' %}" class="text-blue-500 hover:underline">Sign up here</a>
|
||||||
|
</p>
|
||||||
|
<p class="text-center mt-4 text-gray-600 text-sm">
|
||||||
|
Forget the Password? <a href="{% url 'password_reset' %}" class="text-blue-500 hover:underline">Reset here</a>
|
||||||
|
</p>
|
||||||
|
<a href="{% url 'polls:index' %}" class="mt-4 block text-center text-blue-500 hover:underline">Back to Poll</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
<h1>Password reset complete</h1>
|
||||||
|
<p>Your new password has been set. You can log in now on the <a href="{% url 'login' %}">log in page</a>.</p>
|
||||||
12
polls/templates/registration/password_reset_confirm.html
Normal file
12
polls/templates/registration/password_reset_confirm.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{% if validlink %}
|
||||||
|
|
||||||
|
<h1>Set a new password!</h1>
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<input type="submit" value="Change my password">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
|
||||||
2
polls/templates/registration/password_reset_done.html
Normal file
2
polls/templates/registration/password_reset_done.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<h1>Check your inbox.</h1>
|
||||||
|
<p>We've emailed you instructions for setting your password. You should receive the email shortly!</p>
|
||||||
8
polls/templates/registration/password_reset_form.html
Normal file
8
polls/templates/registration/password_reset_form.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<h1>Forgot your password?</h1>
|
||||||
|
<p>Enter your email address below, and we'll email instructions for setting a new one.</p>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<input type="submit" value="Send me instructions!">
|
||||||
|
</form>
|
||||||
46
polls/templates/registration/signup.html
Normal file
46
polls/templates/registration/signup.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Sign Up Page</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-gray-100">
|
||||||
|
<div class="min-h-screen flex items-center justify-center">
|
||||||
|
<div class="bg-white p-8 shadow-md rounded-md w-96">
|
||||||
|
<h2 class="text-2xl font-semibold mb-6">Sign Up</h2>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-4">
|
||||||
|
<p class="block text-gray-700 font-medium">Username</p>
|
||||||
|
{{ form.username }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<p class="block text-gray-700 font-medium">Password</p>
|
||||||
|
{{ form.password1 }}
|
||||||
|
<div class="mb-4">
|
||||||
|
<p class="block text-gray-700 font-medium">Password Confirmation</p>
|
||||||
|
{{ form.password2 }}
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="w-full bg-green-500 text-white py-2 rounded-md hover:bg-green-600 focus:ring-2 focus:ring-green-300 focus:outline-none">Sign Up</button>
|
||||||
|
<!-- text form -->
|
||||||
|
<p class="mt-2 text-gray-600 text-sm">Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</p>
|
||||||
|
<p class="mt-2 text-gray-600 text-sm">Your password can’t be too similar to your other personal information. , must contain at least 8 characters, can’t be entirely numeric.</p>
|
||||||
|
</form>
|
||||||
|
<div class="mt-2 text-gray-600 text-sm">
|
||||||
|
{% if form.errors %}
|
||||||
|
{% for field in form %}
|
||||||
|
{% if field.errors %}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<p class="text-red-500">{{ error }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<p class="mt-4 text-gray-600 text-sm">Already have an account? <a href="{% url 'login' %}" class="text-blue-500 hover:underline">Sign in here</a></p>
|
||||||
|
<a href="{% url 'polls:index' %}" class="mt-4 block text-center text-blue-500 hover:underline">Back to Poll</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -8,4 +8,5 @@ urlpatterns = [
|
|||||||
path("<int:pk>/", views.DetailView.as_view(), name="detail"),
|
path("<int:pk>/", views.DetailView.as_view(), name="detail"),
|
||||||
path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
|
path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
|
||||||
path("<int:question_id>/vote/", views.vote, name="vote"),
|
path("<int:question_id>/vote/", views.vote, name="vote"),
|
||||||
|
path("signup/", views.SignUpView.as_view(), name="signup"),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -3,8 +3,9 @@ from django.shortcuts import get_object_or_404, render
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.views.generic import TemplateView
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
|
from .forms import SignUpForm
|
||||||
from .models import Choice, Question
|
from .models import Choice, Question
|
||||||
|
|
||||||
|
|
||||||
@ -66,6 +67,12 @@ class ResultsView(generic.DetailView):
|
|||||||
return render(self.request, self.template_name, context)
|
return render(self.request, self.template_name, context)
|
||||||
|
|
||||||
|
|
||||||
|
class SignUpView(generic.CreateView):
|
||||||
|
form_class = SignUpForm
|
||||||
|
success_url = reverse_lazy('login')
|
||||||
|
template_name = 'registration/signup.html'
|
||||||
|
|
||||||
|
|
||||||
def vote(request, question_id):
|
def vote(request, question_id):
|
||||||
"""
|
"""
|
||||||
A function that update the database. Add vote count to choice that user vote
|
A function that update the database. Add vote count to choice that user vote
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user