mirror of
https://github.com/Sosokker/ku-polls.git
synced 2025-12-18 13:04: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
|
||||
|
||||
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("polls/", include("polls.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.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db.models import Sum
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class Question(models.Model):
|
||||
|
||||
@ -26,15 +26,22 @@
|
||||
</button>
|
||||
</form>
|
||||
<!--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>
|
||||
</header>
|
||||
<a href=""
|
||||
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">
|
||||
{% if user.is_authenticated %}
|
||||
<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>
|
||||
</a>
|
||||
{% endif %}
|
||||
</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>/results/", views.ResultsView.as_view(), name="results"),
|
||||
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.views import generic
|
||||
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
|
||||
|
||||
|
||||
@ -66,6 +67,12 @@ class ResultsView(generic.DetailView):
|
||||
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):
|
||||
"""
|
||||
A function that update the database. Add vote count to choice that user vote
|
||||
|
||||
Loading…
Reference in New Issue
Block a user