@ -1,8 +1,37 @@ |
||||
from django.contrib import admin |
||||
from django.contrib.auth.admin import UserAdmin |
||||
from .models import User # Import your custom User model |
||||
|
||||
from .models import BaseUser |
||||
class CustomUserAdmin(UserAdmin): |
||||
model = User |
||||
|
||||
# Register your models here. |
||||
# Fields to display in the list view of the admin |
||||
list_display = ['email', 'first_name', 'last_name', 'is_staff', 'is_superuser', 'is_active'] |
||||
|
||||
admin.site.register(BaseUser) |
||||
# Fields to search in the admin |
||||
search_fields = ['email', 'first_name', 'last_name'] |
||||
|
||||
# Default ordering of records in the admin |
||||
ordering = ['email'] |
||||
|
||||
# Fieldsets for the add and change forms in the admin |
||||
fieldsets = ( |
||||
(None, {'fields': ('email', 'password')}), |
||||
('Personal Info', {'fields': ('first_name', 'last_name')}), |
||||
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser')}), |
||||
('Important Dates', {'fields': ('last_login',)}), # Remove 'date_joined' if it doesn't exist |
||||
) |
||||
|
||||
# Fieldsets for the add form in the admin |
||||
add_fieldsets = ( |
||||
(None, { |
||||
'classes': ('wide',), |
||||
'fields': ('email', 'first_name', 'last_name', 'password1', 'password2', 'is_staff', 'is_superuser', 'is_active'), |
||||
}), |
||||
) |
||||
|
||||
# Filters for the list view in the admin |
||||
list_filter = ('is_staff', 'is_superuser', 'is_active') |
||||
|
||||
# Register your custom User model with the custom UserAdmin class |
||||
admin.site.register(User, CustomUserAdmin) |
@ -1,45 +1,52 @@ |
||||
from django import forms |
||||
from django.contrib.auth.forms import UserCreationForm |
||||
from .models import BaseUser |
||||
from django.contrib.auth.forms import AuthenticationForm |
||||
from .models import User |
||||
|
||||
class BaseUserForm(UserCreationForm): |
||||
class Meta: |
||||
model = BaseUser |
||||
fields = [ |
||||
'first_name', |
||||
'last_name', |
||||
'bio', |
||||
'address', |
||||
'contact_number', |
||||
'image', |
||||
'citizenship', |
||||
'certificate', |
||||
'price', |
||||
'role', |
||||
'email', |
||||
] |
||||
password1 = forms.CharField( |
||||
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Password'}), |
||||
label='Password', |
||||
min_length=8, |
||||
class UserRegistrationForm(forms.ModelForm): |
||||
password = forms.CharField( |
||||
widget=forms.PasswordInput(attrs={ |
||||
'class': 'form-control', |
||||
'placeholder': 'Enter your password', |
||||
}) |
||||
) |
||||
password2 = forms.CharField( |
||||
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Confirm Password'}), |
||||
label='Confirm Password', |
||||
min_length=8, |
||||
confirm_password = forms.CharField( |
||||
widget=forms.PasswordInput(attrs={ |
||||
'class': 'form-control', |
||||
'placeholder': 'Confirm your password', |
||||
}) |
||||
) |
||||
|
||||
def clean_password2(self): |
||||
password1 = self.cleaned_data.get('password1') |
||||
password2 = self.cleaned_data.get('password2') |
||||
class Meta: |
||||
model = User |
||||
fields = ['first_name', 'last_name', 'email', 'password'] |
||||
widgets = { |
||||
'first_name': forms.TextInput(attrs={ |
||||
'class': 'form-control', |
||||
'placeholder': 'Enter your first name', |
||||
}), |
||||
'last_name': forms.TextInput(attrs={ |
||||
'class': 'form-control', |
||||
'placeholder': 'Enter your last name', |
||||
}), |
||||
'email': forms.EmailInput(attrs={ |
||||
'class': 'form-control', |
||||
'placeholder': 'Enter your email address', |
||||
}), |
||||
} |
||||
|
||||
def clean(self): |
||||
cleaned_data = super().clean() |
||||
password = cleaned_data.get('password') |
||||
confirm_password = cleaned_data.get('confirm_password') |
||||
|
||||
if password1 and password2 and password1 != password2: |
||||
raise forms.ValidationError("Passwords don't match.") |
||||
return password2 |
||||
if password and confirm_password and password != confirm_password: |
||||
raise forms.ValidationError("Passwords do not match.") |
||||
|
||||
def save(self, commit=True): |
||||
user = super().save(commit=False) |
||||
user.set_password(self.cleaned_data['password1']) |
||||
if commit: |
||||
user.save() |
||||
return user |
||||
class UserLoginForm(AuthenticationForm): |
||||
def __init__(self, *args, **kwargs): |
||||
self.request = kwargs.pop('request', None) |
||||
super(UserLoginForm, self).__init__(*args, **kwargs) |
||||
# Change the username field label and placeholder to 'Email' |
||||
self.fields['username'].label = 'Email' |
||||
self.fields['username'].widget.attrs.update({'placeholder': 'Enter your email'}) |
||||
self.fields['password'].widget.attrs.update({'placeholder': 'Enter your password'}) |
||||
|
@ -0,0 +1,43 @@ |
||||
# Generated by Django 5.1.4 on 2025-01-11 19:36 |
||||
|
||||
import datetime |
||||
import django.utils.timezone |
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('main', '0001_initial'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='user', |
||||
name='bio', |
||||
field=models.CharField(default=datetime.datetime(2025, 1, 11, 19, 36, 0, 579795, tzinfo=datetime.timezone.utc), max_length=200), |
||||
preserve_default=False, |
||||
), |
||||
migrations.AddField( |
||||
model_name='user', |
||||
name='member_since', |
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), |
||||
preserve_default=False, |
||||
), |
||||
migrations.AddField( |
||||
model_name='user', |
||||
name='price', |
||||
field=models.PositiveBigIntegerField(default=10), |
||||
preserve_default=False, |
||||
), |
||||
migrations.AddField( |
||||
model_name='user', |
||||
name='profile', |
||||
field=models.ImageField(blank=True, null=True, upload_to=''), |
||||
), |
||||
migrations.AddField( |
||||
model_name='user', |
||||
name='updated_on', |
||||
field=models.DateField(auto_now=True), |
||||
), |
||||
] |
@ -1,41 +1,110 @@ |
||||
from django.contrib.auth.models import AbstractUser |
||||
from django.db import models |
||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin |
||||
from django.core.mail import send_mail |
||||
from django.utils.encoding import force_bytes |
||||
from django.template.loader import render_to_string |
||||
from django.contrib.auth.tokens import default_token_generator |
||||
from django.conf import settings |
||||
from django.utils.http import urlsafe_base64_encode |
||||
|
||||
class BaseUser(AbstractUser): |
||||
# Additional fields to extend the default user model |
||||
|
||||
# Profile-related fields |
||||
image = models.ImageField(upload_to='user_profiles/', blank=True, null=True) |
||||
bio = models.TextField(blank=True, null=True) |
||||
address = models.TextField(blank=True, null=True) |
||||
contact_number = models.CharField(max_length=15, blank=True, null=True) |
||||
citizenship = models.CharField(max_length=100, blank=True, null=True) |
||||
certificate = models.FileField(upload_to='certificates/', blank=True, null=True) |
||||
|
||||
# Verification and status |
||||
is_verified = models.BooleanField(default=False) |
||||
|
||||
# Financial or business-related fields |
||||
price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) |
||||
ratings = models.DecimalField(max_digits=3, decimal_places=2, default=0.00) |
||||
|
||||
# Role and other identifiers |
||||
role = models.CharField( |
||||
max_length=50, |
||||
choices=[('CLIENT', 'CLIENT'), ('ADMIN', 'ADMIN'), ('SERVICE_PROVIDER', 'SERVICE_PROVIDER')], |
||||
default='CLIENT' |
||||
|
||||
class Service(models.Model): |
||||
name = models.CharField(max_length=20) |
||||
description = models.CharField(max_length=100, blank=True, null=True) |
||||
def __str__(self): |
||||
return self.name |
||||
|
||||
class UserManager(BaseUserManager): |
||||
def create_user(self, first_name, last_name, email, password=None, **extra_fields): |
||||
""" |
||||
Creates and saves a User with the given first name, last name, email, and password. |
||||
""" |
||||
if not email: |
||||
raise ValueError('Users must have an email address') |
||||
|
||||
email = self.normalize_email(email) |
||||
user = self.model( |
||||
first_name=first_name, |
||||
last_name=last_name, |
||||
email=email, |
||||
**extra_fields |
||||
) |
||||
user.set_password(password) |
||||
user.save(using=self._db) |
||||
|
||||
# Send verification email |
||||
try: |
||||
self.send_verification_email(user) |
||||
except: |
||||
print("Couldnot send verification email.") |
||||
|
||||
return user |
||||
|
||||
def create_superuser(self, first_name, last_name, email, password=None, **extra_fields): |
||||
""" |
||||
Creates and saves a superuser with the given first name, last name, email, and password. |
||||
""" |
||||
extra_fields.setdefault('is_staff', True) |
||||
extra_fields.setdefault('is_superuser', True) |
||||
extra_fields.setdefault('is_active', True) |
||||
|
||||
if extra_fields.get('is_staff') is not True: |
||||
raise ValueError('Superuser must have is_staff=True.') |
||||
if extra_fields.get('is_superuser') is not True: |
||||
raise ValueError('Superuser must have is_superuser=True.') |
||||
|
||||
return self.create_user(first_name, last_name, email, password, **extra_fields) |
||||
|
||||
def send_verification_email(self, user): |
||||
# Generate the token and the uid for the verification URL |
||||
token = default_token_generator.make_token(user) |
||||
uid = urlsafe_base64_encode(force_bytes(user.pk)) |
||||
verification_url = f"{settings.FRONTEND_URL}/verify-email/{uid}/{token}/" |
||||
|
||||
subject = "Verify Your Email Address" |
||||
message = render_to_string('emails/verification_email.html', { |
||||
'user': user, |
||||
'verification_url': verification_url, |
||||
}) |
||||
|
||||
send_mail( |
||||
subject, |
||||
message, |
||||
settings.DEFAULT_FROM_EMAIL, |
||||
[user.email], |
||||
fail_silently=False, |
||||
) |
||||
|
||||
# Time-related fields |
||||
|
||||
class User(AbstractBaseUser, PermissionsMixin): |
||||
email = models.EmailField(unique=True) |
||||
first_name = models.CharField(max_length=30) |
||||
last_name = models.CharField(max_length=30) |
||||
is_active = models.BooleanField(default=True) |
||||
is_staff = models.BooleanField(default=False) |
||||
is_superuser = models.BooleanField(default=False) |
||||
profile = models.ImageField(blank=True,null=True) |
||||
price = models.PositiveBigIntegerField(blank=True, null=True) |
||||
bio = models.CharField(max_length=200, blank=True, null=True) |
||||
member_since = models.DateTimeField(auto_now_add=True) |
||||
profile_updated = models.DateTimeField(auto_now=True) |
||||
updated_on = models.DateField(auto_now=True) |
||||
USERNAME_FIELD = 'email' |
||||
REQUIRED_FIELDS = ['first_name', 'last_name'] |
||||
|
||||
# Token field for verification or authentication purposes |
||||
token = models.CharField(max_length=256, blank=True, null=True) |
||||
objects = UserManager() |
||||
|
||||
def __str__(self): |
||||
return self.username |
||||
return self.email |
||||
|
||||
def get_full_name(self): |
||||
return f"{self.first_name} {self.last_name}" |
||||
|
||||
def get_short_name(self): |
||||
return self.first_name |
||||
|
||||
class Meta: |
||||
verbose_name = 'Base User' |
||||
verbose_name_plural = 'Base Users' |
||||
class ServiceRequest(models.Model): |
||||
client = models.ForeignKey(User,on_delete=models.CASCADE,related_name="client") |
||||
service_provider = models.ForeignKey(User,on_delete=models.CASCADE,related_name="client") |
||||
agreed_price = models.DecimalField(max_digits=999,decimal_places=2 , default=0) |
||||
agreed_on = models.DateField(auto_now_add=True) |
||||
is_completed = models.BooleanField(default=False) |
||||
|
@ -0,0 +1,12 @@ |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<title>Verify Your Email Address</title> |
||||
</head> |
||||
<body> |
||||
<p>Hello {{ user.get_full_name }},</p> |
||||
<p>Please click the link below to verify your email address:</p> |
||||
<p><a href="{{ verification_url }}">{{ verification_url }}</a></p> |
||||
<p>If you did not create an account, please ignore this email.</p> |
||||
</body> |
||||
</html> |
@ -1,17 +0,0 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"> |
||||
<title>Document</title> |
||||
</head> |
||||
<body> |
||||
|
||||
<form method="post"> |
||||
{% csrf_token %} |
||||
{{ form.as_p }} |
||||
<button type="submit">Create</button> |
||||
</form> |
||||
</body> |
||||
</html> |
@ -1,5 +0,0 @@ |
||||
<form method="post"> |
||||
{% csrf_token %} |
||||
<p>Are you sure you want to delete {{ object }}?</p> |
||||
<button type="submit">Delete</button> |
||||
</form> |
@ -0,0 +1,63 @@ |
||||
{% extends 'base.html' %} |
||||
|
||||
{% block content %} |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>Login Form</title> |
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
||||
<style> |
||||
.login-container { |
||||
height: 100vh; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
background: #f4f7fc; |
||||
} |
||||
.login-card { |
||||
padding: 2rem; |
||||
border-radius: 8px; |
||||
background: white; |
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
||||
width: 100%; |
||||
max-width: 400px; |
||||
} |
||||
.login-card h2 { |
||||
text-align: center; |
||||
margin-bottom: 1rem; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div class="login-container"> |
||||
<div class="login-card"> |
||||
<h2>Login</h2> |
||||
<form action="#" method="post"> |
||||
{% csrf_token %} |
||||
<div class="mb-3"> |
||||
<label for="email" class="form-label">Email</label> |
||||
<input type="text" class="form-control" id="email" name="email" placeholder="Enter your email" required> |
||||
</div> |
||||
<div class="mb-3"> |
||||
<label for="password" class="form-label">Password</label> |
||||
<input type="password" class="form-control" id="password" name="password" placeholder="Enter your password" required> |
||||
</div> |
||||
<div class="d-flex justify-content-between align-items-center"> |
||||
<div class="form-check"> |
||||
<input type="checkbox" class="form-check-input" id="rememberMe"> |
||||
<label class="form-check-label" for="rememberMe">Remember Me</label> |
||||
</div> |
||||
<a href="#" class="small">Forgot password?</a> |
||||
</div> |
||||
<button type="submit" class="btn btn-primary w-100 mt-3">Login</button> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
||||
</body> |
||||
</html> |
||||
|
||||
{% endblock %} |
@ -0,0 +1,63 @@ |
||||
{% extends 'base.html' %} |
||||
|
||||
{% block content %} |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>Login Form</title> |
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
||||
<style> |
||||
.login-container { |
||||
height: 100vh; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
background: #f4f7fc; |
||||
} |
||||
.login-card { |
||||
padding: 2rem; |
||||
border-radius: 8px; |
||||
background: white; |
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
||||
width: 100%; |
||||
max-width: 400px; |
||||
} |
||||
.login-card h2 { |
||||
text-align: center; |
||||
margin-bottom: 1rem; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div class="login-container"> |
||||
<div class="login-card"> |
||||
<h2>Login</h2> |
||||
<form action="#" method="post"> |
||||
{% csrf_token %} |
||||
<div class="mb-3"> |
||||
<label for="email" class="form-label">Email</label> |
||||
<input type="text" class="form-control" id="email" name="email" placeholder="Enter your email" required> |
||||
</div> |
||||
<div class="mb-3"> |
||||
<label for="password" class="form-label">Password</label> |
||||
<input type="password" class="form-control" id="password" name="password" placeholder="Enter your password" required> |
||||
</div> |
||||
<div class="d-flex justify-content-between align-items-center"> |
||||
<div class="form-check"> |
||||
<input type="checkbox" class="form-check-input" id="rememberMe"> |
||||
<label class="form-check-label" for="rememberMe">Remember Me</label> |
||||
</div> |
||||
<a href="#" class="small">Forgot password?</a> |
||||
</div> |
||||
<button type="submit" class="btn btn-primary w-100 mt-3">Login</button> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
||||
</body> |
||||
</html> |
||||
|
||||
{% endblock %} |
@ -1,65 +0,0 @@ |
||||
{% load static %} |
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>Welcome to Sahara</title> |
||||
<style> |
||||
body { |
||||
font-family: Arial, sans-serif; |
||||
color: #333; |
||||
background-color: #f7f7f7; |
||||
padding: 30px; |
||||
} |
||||
|
||||
.email-container { |
||||
background-color: #ffffff; |
||||
padding: 20px; |
||||
border-radius: 8px; |
||||
max-width: 600px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
h1 { |
||||
color: #2c3e50; |
||||
} |
||||
|
||||
.company-logo { |
||||
max-width: 150px; |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.cta-button { |
||||
background-color: #3498db; |
||||
color: #ffffff; |
||||
padding: 10px 20px; |
||||
border-radius: 5px; |
||||
text-decoration: none; |
||||
display: inline-block; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.cta-button:hover { |
||||
background-color: #2980b9; |
||||
} |
||||
|
||||
p { |
||||
font-size: 16px; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div class="email-container"> |
||||
<h1>Welcome to Sahara!</h1> |
||||
<img src="{% static 'images/sahara_logo.png' %}" alt="Sahara" class="company-logo"> |
||||
<p>Hello {{ user.first_name }},</p> |
||||
<p>Thank you for signing up with Sahara! We're excited to have you on board.</p> |
||||
<p>Please click the button below to activate your account:</p> |
||||
<a href="{{ activation_link }}" class="cta-button">Activate Your Account</a> |
||||
<p>If you did not sign up for this account, please ignore this email.</p> |
||||
<p>Best regards,<br>Sahara Team</p> |
||||
</div> |
||||
</body> |
||||
</html> |
@ -1,14 +0,0 @@ |
||||
Welcome to Sahara! |
||||
|
||||
Hello {{ user.first_name }}, |
||||
|
||||
Thank you for signing up with Sahara! We're excited to have you on board. |
||||
|
||||
Please click the link below to activate your account: |
||||
|
||||
{{ activation_link }} |
||||
|
||||
If you did not sign up for this account, please ignore this email. |
||||
|
||||
Best regards, |
||||
Sahara Team |
@ -0,0 +1,36 @@ |
||||
{% extends 'base.html' %} |
||||
|
||||
{% block content %} |
||||
<div class="container"> |
||||
<h2>Register</h2> |
||||
<form method="post"> |
||||
{% csrf_token %} |
||||
<div class="form-group"> |
||||
<label for="{{ form.first_name.id_for_label }}">First Name</label> |
||||
{{ form.first_name }} |
||||
</div> |
||||
<div class="form-group"> |
||||
<label for="{{ form.last_name.id_for_label }}">Last Name</label> |
||||
{{ form.last_name }} |
||||
</div> |
||||
<div class="form-group"> |
||||
<label for="{{ form.username.id_for_label }}">Username</label> |
||||
{{ form.username }} |
||||
</div> |
||||
<div class="form-group"> |
||||
<label for="{{ form.email.id_for_label }}">Email</label> |
||||
{{ form.email }} |
||||
</div> |
||||
<div class="form-group"> |
||||
<label for="{{ form.password.id_for_label }}">Password</label> |
||||
{{ form.password }} |
||||
</div> |
||||
<div class="form-group"> |
||||
<label for="{{ form.confirm_password.id_for_label }}">Confirm Password</label> |
||||
{{ form.confirm_password }} |
||||
</div> |
||||
<button type="submit" class="btn btn-primary">Register</button> |
||||
</form> |
||||
<p>Already have an account? <a href="{% url 'login' %}">Login here</a>.</p> |
||||
</div> |
||||
{% endblock %} |
@ -1,5 +0,0 @@ |
||||
<form method="post"> |
||||
{% csrf_token %} |
||||
{{ form.as_p }} |
||||
<button type="submit">Update</button> |
||||
</form> |
@ -1,5 +0,0 @@ |
||||
|
||||
{% for user in users %} |
||||
<p><a href="{% url 'update_user' pk=user.pk %}">{{ user }}</a> |
||||
<a href="{% url 'delete_user' pk=user.pk %}">(delete)</a></p> |
||||
{% endfor %} |
@ -0,0 +1,10 @@ |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<title>Email Verification Failed</title> |
||||
</head> |
||||
<body> |
||||
<h1>Email Verification Failed</h1> |
||||
<p>The verification link is invalid or has expired.</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,10 @@ |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<title>Email Verified</title> |
||||
</head> |
||||
<body> |
||||
<h1>Email Verified Successfully</h1> |
||||
<p>Your email has been verified. You can now log in.</p> |
||||
</body> |
||||
</html> |
@ -1,9 +1,11 @@ |
||||
from django.urls import path |
||||
from .views import homeView,send_mail_page,createUserView,activate_account |
||||
from . import views |
||||
|
||||
urlpatterns = [ |
||||
path('',homeView, name="home"), |
||||
path('send-email/',send_mail_page,name="sendmail"), |
||||
path('user/register/',createUserView,name="register"), |
||||
path('activate/<str:token>/', activate_account, name='activate'), |
||||
path('', views.home, name="home"), |
||||
path('register/', views.register, name='register'), |
||||
path('activate/<str:uidb64>/<str:token>/', views.activate_account, name='activate_account'), |
||||
# path('verify-email/<str:uidb64>/<str:token>/', views.verify_email, name='verify_email'), |
||||
path('login/', views.user_login, name='login'), |
||||
path('logout/', views.user_logout, name='logout'), |
||||
] |
@ -1,26 +0,0 @@ |
||||
from django.core.mail import send_mail |
||||
from django.template.loader import render_to_string |
||||
from django.utils.html import strip_tags |
||||
from django.conf import settings |
||||
from django.urls import reverse |
||||
from django.contrib.sites.shortcuts import get_current_site |
||||
|
||||
|
||||
def send_welcome_email(user, request): |
||||
token = 'generated_token_here' |
||||
activation_link = f"{get_current_site(request).domain}{reverse('account:activate', args=[token])}" |
||||
subject = "Welcome to Sahara - Please Activate Your Account" |
||||
|
||||
html_message = render_to_string('welcome_email.html', { |
||||
'user': user, |
||||
'activation_link': activation_link, |
||||
}) |
||||
plain_message = strip_tags(html_message) |
||||
|
||||
send_mail( |
||||
subject, |
||||
plain_message, |
||||
settings.DEFAULT_FROM_EMAIL, |
||||
[user.email], |
||||
html_message=html_message, |
||||
) |
@ -1,63 +1,82 @@ |
||||
from django.shortcuts import render, redirect,HttpResponse |
||||
from django.core.mail import send_mail |
||||
from django.conf import settings |
||||
from django.template.loader import render_to_string |
||||
from django.utils.html import strip_tags |
||||
from django.conf import settings |
||||
from django.urls import reverse |
||||
from django.contrib.sites.shortcuts import get_current_site |
||||
from . forms import BaseUserForm |
||||
from django.contrib import messages |
||||
from django.contrib.auth import login, logout, authenticate |
||||
from django.contrib.auth.tokens import default_token_generator |
||||
# Create your views here. |
||||
from django.utils.http import urlsafe_base64_decode |
||||
from django.contrib.auth.decorators import login_required |
||||
from django.contrib import messages |
||||
from .models import User |
||||
from .forms import UserRegistrationForm, UserLoginForm |
||||
import logging |
||||
|
||||
|
||||
from .models import BaseUser |
||||
logger = logging.getLogger('main') |
||||
def home(request): |
||||
return render(request,"main/home.html") |
||||
|
||||
def homeView(request): |
||||
return HttpResponse("home") |
||||
|
||||
def createUserView(request): |
||||
def register(request): |
||||
if request.method == 'POST': |
||||
form = BaseUserForm(request.POST, request.FILES) |
||||
print(form) |
||||
form = UserRegistrationForm(request.POST) |
||||
if form.is_valid(): |
||||
form.save() |
||||
form.is_a |
||||
#return redirect('home') |
||||
return HttpResponse("<h1>User Created</h1>") |
||||
else: |
||||
form = BaseUserForm() |
||||
return render(request, 'main/create_user.html', { |
||||
'form': form |
||||
}) |
||||
|
||||
user = form.save(commit=False) |
||||
user.set_password(form.cleaned_data['password']) |
||||
user.save() |
||||
|
||||
def send_mail_page(): |
||||
address = "sajeshmaan@gmail.com" |
||||
subject = "Congrts Team Flash" |
||||
message = "Congrts Team Flash hackx committe has announced your team as a winner" |
||||
try: |
||||
send_mail(subject, message, settings.EMAIL_HOST_USER, [address,'rajakiaryal0@gmail.com']) |
||||
result= 'Email sent successfully' |
||||
user.send_verification_email() |
||||
messages.success(request, 'Registration successful! Please check your email to activate your account.') |
||||
except Exception as e: |
||||
result = f'Error sending email: {e}' |
||||
|
||||
|
||||
logger.error(f"Error sending verification email: {e}") |
||||
messages.error(request, 'Error sending verification email. Please try again later.') |
||||
|
||||
return redirect('login') |
||||
else: |
||||
form = UserRegistrationForm() |
||||
return render(request, 'main/register.html', {'form': form}) |
||||
|
||||
def activate_account(request,token): |
||||
return |
||||
def activate_account(request, uidb64, token): |
||||
try: |
||||
# Decode token and retrieve user |
||||
user = BaseUser.objects.get(email__iexact="") |
||||
if user: |
||||
# Activate user account |
||||
uid = urlsafe_base64_decode(uidb64).decode() |
||||
user = User.objects.get(pk=uid) |
||||
except (TypeError, ValueError, OverflowError, User.DoesNotExist): |
||||
user = None |
||||
|
||||
if user is not None and default_token_generator.check_token(user, token): |
||||
user.is_active = True |
||||
user.save() |
||||
messages.success(request, "Account activated successfully!") |
||||
return redirect('login') # Redirect to the login page |
||||
messages.success(request, 'Your account has been activated. You can now log in.') |
||||
return redirect('login') |
||||
else: |
||||
messages.error(request, "Invalid activation link.") |
||||
except Exception as e: |
||||
messages.error(request, str(e)) |
||||
return redirect('home') # Redirect to homepage in case of error |
||||
messages.error(request, 'Invalid activation link.') |
||||
return redirect('register') |
||||
|
||||
def user_login(request): |
||||
print(request.user.is_authenticated) |
||||
if request.user.is_authenticated: |
||||
return redirect('home') |
||||
|
||||
if request.method == 'POST': |
||||
email = request.POST['email'] |
||||
password = request.POST['password'] |
||||
user = authenticate(request, email = email, password = password) |
||||
if user is not None: |
||||
form = login(request, user) |
||||
messages.success(request, f' welcome {user} !!') |
||||
return redirect('home') |
||||
else: |
||||
messages.info(request, f'account done not exit plz sign in') |
||||
|
||||
messages.info(request, f'You are Already Logged in as {request.user}') |
||||
return render(request, 'main/login.html', {'title':'log in'}) |
||||
|
||||
|
||||
@login_required |
||||
def user_logout(request): |
||||
logout(request) |
||||
messages.success(request, 'You have been logged out.') |
||||
return redirect('login') |
||||
|
||||
# def verify_email(request, uidb64, token): |
||||
# # This view is redundant if it does the same as activate_account |
||||
# # Consider removing or assigning a different purpose |
||||
# pass |
Before Width: | Height: | Size: 273 KiB |
Before Width: | Height: | Size: 273 KiB |
Before Width: | Height: | Size: 273 KiB |
Before Width: | Height: | Size: 273 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 273 KiB |
@ -1,12 +1,7 @@ |
||||
from django.contrib import admin |
||||
from django.urls import path, include |
||||
from django.conf import settings |
||||
from django.conf.urls.static import static |
||||
|
||||
urlpatterns = [ |
||||
path('admin/', admin.site.urls), |
||||
path('',include("main.urls")) |
||||
path('', include('main.urls')), |
||||
] |
||||
|
||||
if settings.DEBUG: |
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) |
@ -0,0 +1,38 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>Sahara</title> |
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> |
||||
<link rel="stylesheet" href="styles.css"> |
||||
</head> |
||||
<body> |
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary"> |
||||
<div class="container-fluid"> |
||||
<a class="navbar-brand" href="#"><img src="img/logofinal.png" height="50px" width="75px" alt="Logo"></a> |
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation"> |
||||
<span class="navbar-toggler-icon"></span> |
||||
</button> |
||||
<ul class="nav justify-content-center"> |
||||
<li class="nav-item"> |
||||
<a class="nav-link active" aria-current="page" href="#">Home</a> |
||||
</li> |
||||
<li class="nav-item"> |
||||
<a class="nav-link" href="#">About us</a> |
||||
</li> |
||||
<li class="nav-item"> |
||||
<a class="nav-link" href="#">Services</a> |
||||
</li> |
||||
|
||||
</ul> |
||||
<div class="login"> |
||||
<a href="#" class="btn btn-outline-primary">Login</a> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</nav> |
||||
|
||||
{% block content %} |
||||
|
||||
{% endblock %} |