main
Babit Shrestha 6 months ago
parent 480d7501be
commit 64a015ac7b
  1. BIN
      sahara/db.sqlite3
  2. BIN
      sahara/main/__pycache__/__init__.cpython-312.pyc
  3. BIN
      sahara/main/__pycache__/admin.cpython-312.pyc
  4. BIN
      sahara/main/__pycache__/apps.cpython-312.pyc
  5. BIN
      sahara/main/__pycache__/forms.cpython-312.pyc
  6. BIN
      sahara/main/__pycache__/managers.cpython-312.pyc
  7. BIN
      sahara/main/__pycache__/models.cpython-312.pyc
  8. BIN
      sahara/main/__pycache__/urls.cpython-312.pyc
  9. BIN
      sahara/main/__pycache__/views.cpython-312.pyc
  10. 35
      sahara/main/admin.py
  11. 83
      sahara/main/forms.py
  12. 40
      sahara/main/migrations/0001_initial.py
  13. 43
      sahara/main/migrations/0002_user_bio_user_member_since_user_price_user_profile_and_more.py
  14. BIN
      sahara/main/migrations/__pycache__/0001_initial.cpython-312.pyc
  15. BIN
      sahara/main/migrations/__pycache__/0002_alter_baseuser_options_baseuser_date_joined_and_more.cpython-312.pyc
  16. BIN
      sahara/main/migrations/__pycache__/0002_alter_baseuser_username.cpython-312.pyc
  17. BIN
      sahara/main/migrations/__pycache__/0002_user_bio_user_member_since_user_price_user_profile_and_more.cpython-312.pyc
  18. BIN
      sahara/main/migrations/__pycache__/0003_alter_baseuser_price.cpython-312.pyc
  19. BIN
      sahara/main/migrations/__pycache__/0003_remove_baseuser_role.cpython-312.pyc
  20. BIN
      sahara/main/migrations/__pycache__/0004_alter_baseuser_managers_baseuser_role.cpython-312.pyc
  21. BIN
      sahara/main/migrations/__pycache__/0005_alter_baseuser_managers.cpython-312.pyc
  22. BIN
      sahara/main/migrations/__pycache__/0006_remove_baseuser_username.cpython-312.pyc
  23. BIN
      sahara/main/migrations/__pycache__/__init__.cpython-312.pyc
  24. 133
      sahara/main/models.py
  25. 12
      sahara/main/templates/emails/verification_email.html
  26. 17
      sahara/main/templates/main/create_user.html
  27. 5
      sahara/main/templates/main/delete_user.html
  28. 63
      sahara/main/templates/main/home.html
  29. 63
      sahara/main/templates/main/login.html
  30. 65
      sahara/main/templates/main/mail/welcome_email.html
  31. 14
      sahara/main/templates/main/mail/welcome_email.txt
  32. 36
      sahara/main/templates/main/register.html
  33. 5
      sahara/main/templates/main/update_user.html
  34. 5
      sahara/main/templates/main/user_list.html
  35. 10
      sahara/main/templates/main/verification_failed.html
  36. 10
      sahara/main/templates/main/verification_success.html
  37. 12
      sahara/main/urls.py
  38. 26
      sahara/main/utilities.py
  39. 115
      sahara/main/views.py
  40. BIN
      sahara/media/Screenshot_1.png
  41. BIN
      sahara/media/Screenshot_1_ADxCcNz.png
  42. BIN
      sahara/media/Screenshot_1_Nr3wRlz.png
  43. BIN
      sahara/media/Screenshot_1_Y0GUvRC.png
  44. BIN
      sahara/media/Screenshot_2025-01-10_182515.png
  45. BIN
      sahara/media/Screenshot_2025-01-10_182515_KdukpRJ.png
  46. BIN
      sahara/media/uploads/citizenship/Screenshot_1.png
  47. BIN
      sahara/sahara/__pycache__/__init__.cpython-312.pyc
  48. BIN
      sahara/sahara/__pycache__/settings.cpython-312.pyc
  49. BIN
      sahara/sahara/__pycache__/urls.cpython-312.pyc
  50. BIN
      sahara/sahara/__pycache__/wsgi.cpython-312.pyc
  51. 2
      sahara/sahara/asgi.py
  52. 58
      sahara/sahara/settings.py
  53. 9
      sahara/sahara/urls.py
  54. 2
      sahara/sahara/wsgi.py
  55. 38
      sahara/templates/base.html

Binary file not shown.

@ -1,8 +1,37 @@
from django.contrib import admin 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 import forms
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.forms import AuthenticationForm
from .models import BaseUser from .models import User
class BaseUserForm(UserCreationForm): class UserRegistrationForm(forms.ModelForm):
class Meta: password = forms.CharField(
model = BaseUser widget=forms.PasswordInput(attrs={
fields = [ 'class': 'form-control',
'first_name', 'placeholder': 'Enter your password',
'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,
) )
password2 = forms.CharField( confirm_password = forms.CharField(
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Confirm Password'}), widget=forms.PasswordInput(attrs={
label='Confirm Password', 'class': 'form-control',
min_length=8, 'placeholder': 'Confirm your password',
})
) )
def clean_password2(self): class Meta:
password1 = self.cleaned_data.get('password1') model = User
password2 = self.cleaned_data.get('password2') 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: if password and confirm_password and password != confirm_password:
raise forms.ValidationError("Passwords don't match.") raise forms.ValidationError("Passwords do not match.")
return password2
def save(self, commit=True): class UserLoginForm(AuthenticationForm):
user = super().save(commit=False) def __init__(self, *args, **kwargs):
user.set_password(self.cleaned_data['password1']) self.request = kwargs.pop('request', None)
if commit: super(UserLoginForm, self).__init__(*args, **kwargs)
user.save() # Change the username field label and placeholder to 'Email'
return user 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'})

@ -1,8 +1,5 @@
# Generated by Django 5.1.4 on 2025-01-11 12:36 # Generated by Django 5.1.4 on 2025-01-11 17:02
import django.contrib.auth.models
import django.contrib.auth.validators
import django.utils.timezone
from django.db import migrations, models from django.db import migrations, models
@ -16,41 +13,22 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='BaseUser', name='User',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')), ('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), ('email', models.EmailField(max_length=254, unique=True)),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), ('first_name', models.CharField(max_length=30)),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), ('last_name', models.CharField(max_length=30)),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), ('is_active', models.BooleanField(default=True)),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), ('is_staff', models.BooleanField(default=False)),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), ('is_superuser', models.BooleanField(default=False)),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('image', models.ImageField(blank=True, null=True, upload_to='user_profiles/')),
('bio', models.TextField(blank=True, null=True)),
('address', models.TextField(blank=True, null=True)),
('contact_number', models.CharField(blank=True, max_length=15, null=True)),
('citizenship', models.CharField(blank=True, max_length=100, null=True)),
('certificate', models.FileField(blank=True, null=True, upload_to='certificates/')),
('is_verified', models.BooleanField(default=False)),
('price', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
('ratings', models.DecimalField(decimal_places=2, default=0.0, max_digits=3)),
('role', models.CharField(choices=[('CLIENT', 'CLIENT'), ('ADMIN', 'ADMIN'), ('SERVICE_PROVIDER', 'SERVICE_PROVIDER')], default='CLIENT', max_length=50)),
('member_since', models.DateTimeField(auto_now_add=True)),
('profile_updated', models.DateTimeField(auto_now=True)),
('token', models.CharField(blank=True, max_length=256, null=True)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
], ],
options={ options={
'verbose_name': 'Base User', 'abstract': False,
'verbose_name_plural': 'Base Users',
}, },
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
), ),
] ]

@ -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.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 class Service(models.Model):
name = models.CharField(max_length=20)
# Profile-related fields description = models.CharField(max_length=100, blank=True, null=True)
image = models.ImageField(upload_to='user_profiles/', blank=True, null=True) def __str__(self):
bio = models.TextField(blank=True, null=True) return self.name
address = models.TextField(blank=True, null=True)
contact_number = models.CharField(max_length=15, blank=True, null=True) class UserManager(BaseUserManager):
citizenship = models.CharField(max_length=100, blank=True, null=True) def create_user(self, first_name, last_name, email, password=None, **extra_fields):
certificate = models.FileField(upload_to='certificates/', blank=True, null=True) """
Creates and saves a User with the given first name, last name, email, and password.
# Verification and status """
is_verified = models.BooleanField(default=False) if not email:
raise ValueError('Users must have an email address')
# Financial or business-related fields
price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) email = self.normalize_email(email)
ratings = models.DecimalField(max_digits=3, decimal_places=2, default=0.00) user = self.model(
first_name=first_name,
# Role and other identifiers last_name=last_name,
role = models.CharField( email=email,
max_length=50, **extra_fields
choices=[('CLIENT', 'CLIENT'), ('ADMIN', 'ADMIN'), ('SERVICE_PROVIDER', 'SERVICE_PROVIDER')], )
default='CLIENT' 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) 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 objects = UserManager()
token = models.CharField(max_length=256, blank=True, null=True)
def __str__(self): 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: class ServiceRequest(models.Model):
verbose_name = 'Base User' client = models.ForeignKey(User,on_delete=models.CASCADE,related_name="client")
verbose_name_plural = 'Base Users' 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 django.urls import path
from .views import homeView,send_mail_page,createUserView,activate_account from . import views
urlpatterns = [ urlpatterns = [
path('',homeView, name="home"), path('', views.home, name="home"),
path('send-email/',send_mail_page,name="sendmail"), path('register/', views.register, name='register'),
path('user/register/',createUserView,name="register"), path('activate/<str:uidb64>/<str:token>/', views.activate_account, name='activate_account'),
path('activate/<str:token>/', activate_account, name='activate'), # 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.shortcuts import render, redirect,HttpResponse
from django.core.mail import send_mail from django.contrib.auth import login, logout, authenticate
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.tokens import default_token_generator 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': if request.method == 'POST':
form = BaseUserForm(request.POST, request.FILES) form = UserRegistrationForm(request.POST)
print(form)
if form.is_valid(): if form.is_valid():
form.save() user = form.save(commit=False)
form.is_a user.set_password(form.cleaned_data['password'])
#return redirect('home') user.save()
return HttpResponse("<h1>User Created</h1>")
else:
form = BaseUserForm()
return render(request, 'main/create_user.html', {
'form': form
})
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: try:
send_mail(subject, message, settings.EMAIL_HOST_USER, [address,'rajakiaryal0@gmail.com']) user.send_verification_email()
result= 'Email sent successfully' messages.success(request, 'Registration successful! Please check your email to activate your account.')
except Exception as e: 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): def activate_account(request, uidb64, token):
return
try: try:
# Decode token and retrieve user uid = urlsafe_base64_decode(uidb64).decode()
user = BaseUser.objects.get(email__iexact="") user = User.objects.get(pk=uid)
if user: except (TypeError, ValueError, OverflowError, User.DoesNotExist):
# Activate user account user = None
if user is not None and default_token_generator.check_token(user, token):
user.is_active = True user.is_active = True
user.save() user.save()
messages.success(request, "Account activated successfully!") messages.success(request, 'Your account has been activated. You can now log in.')
return redirect('login') # Redirect to the login page return redirect('login')
else: else:
messages.error(request, "Invalid activation link.") messages.error(request, 'Invalid activation link.')
except Exception as e: return redirect('register')
messages.error(request, str(e))
return redirect('home') # Redirect to homepage in case of error 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

@ -4,7 +4,7 @@ ASGI config for sahara project.
It exposes the ASGI callable as a module-level variable named ``application``. It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
""" """
import os import os

@ -1,37 +1,33 @@
""" """
Django settings for sahara project. Django settings for sahara project.
Generated by 'django-admin startproject' using Django 5.0.6. Generated by 'django-admin startproject' using Django 5.1.4.
For more information on this file, see For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/ https://docs.djangoproject.com/en/5.1/topics/settings/
For the full list of settings and their values, see For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/ https://docs.djangoproject.com/en/5.1/ref/settings/
""" """
from pathlib import Path from pathlib import Path
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
load_dotenv()
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
import os
load_dotenv()
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-dw78ln%=0i^uy4zj78lkx=p_98ik3%h@u%wod1va651^1jyy*m' SECRET_KEY = 'django-insecure-a#y#*r@98v*f)e!83s5dk9it704i)l7#x-e%59=_%ts%&4lt^2'
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
ALLOWED_HOSTS = ["*"] ALLOWED_HOSTS = ["*"]
FRONTEND_URL = 'http://localhost:8000'
# Application definition # Application definition
@ -61,7 +57,7 @@ ROOT_URLCONF = 'sahara.urls'
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], 'DIRS': [BASE_DIR / "templates/"],
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
@ -76,19 +72,9 @@ TEMPLATES = [
WSGI_APPLICATION = 'sahara.wsgi.application' WSGI_APPLICATION = 'sahara.wsgi.application'
####EMAIL CONF
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ.get("EMAIL_ADDRESS")
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_PASSWORD")
# Database # Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases # https://docs.djangoproject.com/en/5.1/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { 'default': {
@ -99,7 +85,7 @@ DATABASES = {
# Password validation # Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
@ -118,7 +104,7 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/ # https://docs.djangoproject.com/en/5.1/topics/i18n/
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-us'
@ -130,7 +116,23 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/ # https://docs.djangoproject.com/en/5.1/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
####EMAIL CONF
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ.get("EMAIL_ADDRESS")
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_PASSWORD")
STATIC_URL = 'static/' STATIC_URL = 'static/'
@ -140,10 +142,10 @@ STATIC_URL = 'static/'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
AUTH_USER_MODEL = 'main.BaseUser' AUTH_USER_MODEL = 'main.User'
STATIC_URL = '/static/' STATIC_URL = '/static/'
#STATICFILES_DIRS = [BASE_DIR / "static"]
STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_URL = '/media/' MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

@ -1,12 +1,7 @@
from django.contrib import admin from django.contrib import admin
from django.urls import path,include from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), 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)

@ -4,7 +4,7 @@ WSGI config for sahara project.
It exposes the WSGI callable as a module-level variable named ``application``. It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
""" """
import os import os

@ -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 %}
Loading…
Cancel
Save