major updation

This commit is contained in:
2025-08-20 11:35:11 +05:30
parent a6f62de2c4
commit 27d013e853
19 changed files with 578 additions and 60 deletions
+7 -5
View File
@@ -26,7 +26,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'core',
'core.apps.CoreConfig',
]
AUTH_USER_MODEL = 'core.User'
@@ -67,9 +67,9 @@ WSGI_APPLICATION = 'civicfix.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'civixfix_db',
'USER': 'civicfix_user',
'PASSWORD': 'Gokul@2001',
'NAME': 'civicfix',
'USER': 'admin',
'PASSWORD': 'qwerty123',
'HOST': 'localhost',
'PORT': '5432',
}
@@ -116,5 +116,7 @@ STATIC_URL = 'static/'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_REDIRECT_URL = 'home'
# Add these settings
LOGIN_REDIRECT_URL = 'citizen_dashboard'
LOGIN_URL = 'login'
LOGOUT_REDIRECT_URL = 'home'
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+30 -2
View File
@@ -1,6 +1,6 @@
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import User
from .models import User, Issue
class CitizenRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
@@ -18,4 +18,32 @@ class CitizenRegistrationForm(UserCreationForm):
if commit:
user.save()
return user
return user
class CitizenRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
phone = forms.CharField(max_length=15, required=False)
class Meta:
model = User
fields = ['username', 'email', 'phone', 'password1', 'password2']
def save(self, commit=True):
user = super().save(commit=False)
user.email = self.cleaned_data['email']
user.phone = self.cleaned_data['phone']
user.is_citizen = True
if commit:
user.save()
return user
class IssueForm(forms.ModelForm):
class Meta:
model = Issue
fields = ['title', 'description', 'category', 'location', 'latitude', 'longitude', 'photo']
widgets = {
'latitude': forms.HiddenInput(),
'longitude': forms.HiddenInput(),
'description': forms.Textarea(attrs={'rows': 4, 'placeholder': 'Describe the issue in detail...'}),
}
+32 -3
View File
@@ -1,8 +1,11 @@
# Generated by Django 5.2.5 on 2025-08-18 15:07
# Generated by Django 5.2.5 on 2025-08-20 06:30
import django.contrib.auth.models
import django.contrib.auth.validators
import django.core.validators
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
@@ -15,6 +18,15 @@ class Migration(migrations.Migration):
]
operations = [
migrations.CreateModel(
name='IssueCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('description', models.TextField(blank=True)),
('icon', models.CharField(default='fas fa-exclamation-circle', max_length=50)),
],
),
migrations.CreateModel(
name='User',
fields=[
@@ -33,8 +45,8 @@ class Migration(migrations.Migration):
('is_moderator', models.BooleanField(default=False)),
('is_resolver', models.BooleanField(default=False)),
('phone', models.CharField(blank=True, max_length=15, 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')),
('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')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to.', related_name='core_user_groups', related_query_name='core_user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='core_user_permissions', related_query_name='core_user', to='auth.permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
@@ -45,4 +57,21 @@ class Migration(migrations.Migration):
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.CreateModel(
name='Issue',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('description', models.TextField()),
('location', models.CharField(max_length=200)),
('latitude', models.FloatField()),
('longitude', models.FloatField()),
('photo', models.ImageField(blank=True, null=True, upload_to='issue_photos/', validators=[django.core.validators.FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])])),
('status', models.CharField(choices=[('reported', 'Reported'), ('acknowledged', 'Acknowledged'), ('in_progress', 'In Progress'), ('resolved', 'Resolved')], default='reported', max_length=20)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('reporter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reported_issues', to=settings.AUTH_USER_MODEL)),
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.issuecategory')),
],
),
]
+49 -2
View File
@@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.urls import reverse
from django.core.validators import FileExtensionValidator
class User(AbstractUser):
is_citizen = models.BooleanField(default=False)
@@ -8,5 +9,51 @@ class User(AbstractUser):
is_resolver = models.BooleanField(default=False)
phone = models.CharField(max_length=15, blank=True, null=True)
def get_absolute_url(self):
return reverse('home')
groups = models.ManyToManyField(
'auth.Group',
verbose_name='groups',
blank=True,
help_text='The groups this user belongs to.',
related_name='core_user_groups',
related_query_name='core_user',
)
user_permissions = models.ManyToManyField(
'auth.Permission',
verbose_name='user permissions',
blank=True,
help_text='Specific permissions for this user.',
related_name='core_user_permissions',
related_query_name='core_user',
)
class IssueCategory(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
icon = models.CharField(max_length=50, default='fas fa-exclamation-circle')
def __str__(self):
return self.name
class Issue(models.Model):
STATUS_CHOICES = [
('reported', 'Reported'),
('acknowledged', 'Acknowledged'),
('in_progress', 'In Progress'),
('resolved', 'Resolved'),
]
title = models.CharField(max_length=200)
description = models.TextField()
category = models.ForeignKey(IssueCategory, on_delete=models.SET_NULL, null=True, blank=True)
reporter = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reported_issues')
location = models.CharField(max_length=200)
latitude = models.FloatField()
longitude = models.FloatField()
photo = models.ImageField(upload_to='issue_photos/', blank=True, null=True,
validators=[FileExtensionValidator(['jpg', 'jpeg', 'png', 'gif'])])
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='reported')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
+49 -25
View File
@@ -35,32 +35,56 @@
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="container">
<a class="navbar-brand" href="{% url 'home' %}">
<i class="fas fa-bullhorn me-2"></i>Civixfix
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link active" href="{% url 'home' %}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#features">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#how-it-works">How It Works</a>
</li>
</ul>
<div class="d-flex">
<a href="{% url 'login' %}" class="btn btn-outline-light me-2">Login</a>
<a href="{% url 'register' %}" class="btn btn-primary">Register</a>
</div>
</div>
<div class="container">
<a class="navbar-brand" href="{% url 'home' %}">
<i class="fas fa-bullhorn me-2"></i>Civixfix
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link active" href="{% url 'home' %}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#features">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#how-it-works">How It Works</a>
</li>
{% if user.is_authenticated and user.is_citizen %}
<li class="nav-item">
<a class="nav-link" href="{% url 'citizen_dashboard' %}">Dashboard</a>
</li>
{% endif %}
</ul>
<div class="d-flex">
{% if user.is_authenticated %}
<div class="dropdown">
<button class="btn btn-outline-light dropdown-toggle" type="button" data-bs-toggle="dropdown">
<i class="fas fa-user me-1"></i> {{ user.username }}
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="{% url 'citizen_dashboard' %}">Dashboard</a></li>
<li><a class="dropdown-item" href="#">Profile</a></li>
<li><hr class="dropdown-divider"></li>
<li>
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit" class="dropdown-item">Logout</button>
</form>
</li>
</ul>
</div>
{% else %}
<a href="{% url 'login' %}" class="btn btn-outline-light me-2">Login</a>
<a href="{% url 'register' %}" class="btn btn-primary">Register</a>
{% endif %}
</div>
</div>
</nav>
</div>
</nav>
<!-- Main Content -->
<main>
@@ -0,0 +1,240 @@
{% extends "core/base.html" %}
{% block title %}Citizen Dashboard - CivixFix{% endblock %}
{% block extra_css %}
<style>
.dashboard-card {
transition: transform 0.2s;
}
.dashboard-card:hover {
transform: translateY(-2px);
}
.map-container {
height: 300px;
border-radius: 8px;
overflow: hidden;
border: 2px dashed #dee2e6;
}
.issue-status {
font-size: 0.8rem;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid py-4">
<div class="row">
<!-- Sidebar - Quick Actions -->
<div class="col-md-3">
<div class="card shadow-sm dashboard-card">
<div class="card-body text-center">
<h5 class="card-title">Welcome, {{ user.username }}</h5>
<p class="text-muted">Citizen Dashboard</p>
<div class="d-grid gap-2 mb-3">
<button class="btn btn-primary btn-lg" data-bs-toggle="modal" data-bs-target="#reportIssueModal">
<i class="fas fa-plus me-2"></i>Report New Issue
</button>
</div>
<hr>
<h6>Quick Stats</h6>
<div class="row text-center">
<div class="col-6">
<div class="bg-light p-2 rounded">
<h4 class="mb-0 text-primary">{{ user_issues.count }}</h4>
<small>My Reports</small>
</div>
</div>
<div class="col-6">
<div class="bg-light p-2 rounded">
<h4 class="mb-0 text-success">
{{ resolved_count }}
</h4>
<small>Resolved</small>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content - Recent Issues -->
<div class="col-md-9">
<!-- Welcome Message -->
<div class="card shadow-sm dashboard-card mb-4">
<div class="card-body">
<h4>Welcome to CivixFix!</h4>
<p class="text-muted mb-0">
Report community issues, track their progress, and help make your neighborhood better.
Start by reporting an issue using the button on the left.
</p>
</div>
</div>
<!-- My Recent Issues -->
<div class="card shadow-sm dashboard-card">
<div class="card-header">
<h5 class="mb-0">My Recent Reports</h5>
</div>
<div class="card-body">
{% for issue in user_issues %}
<div class="card mb-3">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div class="flex-grow-1">
<h6 class="card-title mb-1">{{ issue.title }}</h6>
<p class="card-text text-muted mb-2 small">
{{ issue.description|truncatewords:15 }}
</p>
<div class="d-flex gap-2 align-items-center">
<span class="badge bg-secondary">{{ issue.category.name|default:"No Category" }}</span>
<span class="badge bg-{% if issue.status == 'resolved' %}success{% elif issue.status == 'in_progress' %}warning{% else %}primary{% endif %} issue-status">
{{ issue.get_status_display }}
</span>
<small class="text-muted">{{ issue.created_at|date:"M d, Y" }}</small>
</div>
</div>
{% if issue.photo %}
<div class="ms-3">
<img src="{{ issue.photo.url }}" alt="Issue photo"
class="img-fluid rounded" style="max-height: 60px; max-width: 80px;">
</div>
{% endif %}
</div>
</div>
</div>
{% empty %}
<div class="text-center py-4">
<i class="fas fa-inbox fa-3x text-muted mb-3"></i>
<h5>No issues reported yet</h5>
<p class="text-muted">Click "Report New Issue" to get started!</p>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<!-- Report Issue Modal -->
<div class="modal fade" id="reportIssueModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Report New Issue</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="issueForm" method="post" enctype="multipart/form-data" action="{% url 'report_issue' %}">
{% csrf_token %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show mb-3">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Issue Title*</label>
{{ issue_form.title }}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Category</label>
{{ issue_form.category }}
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Description*</label>
{{ issue_form.description }}
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Location*</label>
{{ issue_form.location }}
<small class="text-muted">Click on the map to select location</small>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Photo (Optional)</label>
{{ issue_form.photo }}
</div>
</div>
</div>
<!-- Hidden latitude/longitude fields -->
{{ issue_form.latitude }}
{{ issue_form.longitude }}
<div class="map-container mb-3">
<div id="map" style="height: 100%;"></div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" form="issueForm" class="btn btn-primary">
<i class="fas fa-paper-plane me-2"></i>Report Issue
</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
<script>
$(document).ready(function() {
// Initialize map
const map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors'
}).addTo(map);
let marker = null;
// Add click event to map
map.on('click', function(e) {
if (marker) {
map.removeLayer(marker);
}
marker = L.marker(e.latlng).addTo(map)
.bindPopup('Selected location').openPopup();
// Update form fields
$('#id_latitude').val(e.latlng.lat);
$('#id_longitude').val(e.latlng.lng);
// Reverse geocode to get address
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${e.latlng.lat}&lon=${e.latlng.lng}`)
.then(response => response.json())
.then(data => {
$('#id_location').val(data.display_name || 'Selected location');
});
});
// Add Bootstrap classes to form fields
$('input:not([type="file"]), select, textarea').addClass('form-control');
$('input[type="file"]').addClass('form-control-file');
// Add specific classes to description field
$('#id_description').addClass('form-control').attr('rows', '3');
});
</script>
{% endblock %}
+54
View File
@@ -0,0 +1,54 @@
{% extends "core/base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card shadow">
<div class="card-body p-5">
<h2 class="card-title text-center mb-4">Login to Your Account</h2>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
<form method="post">
{% csrf_token %}
<div class="mb-3">
<label for="id_username" class="form-label">Username</label>
<input type="text" name="username" class="form-control" id="id_username" required>
</div>
<div class="mb-4">
<label for="id_password" class="form-label">Password</label>
<input type="password" name="password" class="form-control" id="id_password" required>
</div>
<div class="d-grid mb-3">
<button type="submit" class="btn btn-primary btn-lg">Login</button>
</div>
<div class="text-center">
<a href="#" class="text-decoration-none">Forgot password?</a>
</div>
</form>
<hr class="my-4">
<p class="text-center text-muted">
Don't have an account? <a href="{% url 'register' %}" class="text-decoration-none">Register here</a>
</p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
+32 -17
View File
@@ -1,5 +1,4 @@
{% extends "core/base.html" %}
{% block title %}Register as Citizen{% endblock %}
{% block content %}
@@ -9,38 +8,50 @@
<div class="card shadow">
<div class="card-body p-5">
<h2 class="card-title text-center mb-4">Create Citizen Account</h2>
<form method="post">
{% csrf_token %}
{# Messages block - FIXED SYNTAX #}
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{# Form errors block - FIXED SYNTAX #}
{% if form.errors %}
<div class="alert alert-danger">
<strong>Error!</strong> Please correct the following:
<ul>
<div class="alert alert-danger">
<strong>Error!</strong> Please correct the following:
<ul>
{% for field, errors in form.errors.items %}
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
{% endfor %}
</ul>
</div>
</ul>
</div>
{% endif %}
<div class="mb-3">
<label for="id_username" class="form-label">Username</label>
{{ form.username }}
<small class="text-muted">Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</small>
</div>
<div class="mb-3">
<label for="id_email" class="form-label">Email</label>
{{ form.email }}
</div>
<div class="mb-3">
<label for="id_phone" class="form-label">Phone (Optional)</label>
{{ form.phone }}
</div>
<div class="mb-3">
<label for="id_password1" class="form-label">Password</label>
{{ form.password1 }}
@@ -53,20 +64,20 @@
</ul>
</small>
</div>
<div class="mb-4">
<label for="id_password2" class="form-label">Password Confirmation</label>
{{ form.password2 }}
<small class="text-muted">Enter the same password as before, for verification.</small>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary btn-lg">Register</button>
</div>
</form>
<hr class="my-4">
<p class="text-center text-muted">
Already have an account? <a href="{% url 'login' %}" class="text-decoration-none">Login here</a>
</p>
@@ -79,10 +90,14 @@
{% block extra_js %}
<script>
// Add Bootstrap classes to form fields
$(document).ready(function() {
$('input').addClass('form-control');
$(document).ready(function () {
// Add Bootstrap classes to all input fields
$('input:not([type="checkbox"]):not([type="radio"])').addClass('form-control');
$('input[type="checkbox"]').removeClass('form-control').addClass('form-check-input');
$('input[type="radio"]').removeClass('form-control').addClass('form-check-input');
// Add Bootstrap classes to select fields
$('select').addClass('form-select');
});
</script>
{% endblock %}
+3 -1
View File
@@ -5,6 +5,8 @@ from . import views
urlpatterns = [
path('', views.home, name='home'),
path('register/', views.register, name='register'),
path('login/', auth_views.LoginView.as_view(template_name='core/login.html'), name='login'),
path('login/', views.custom_login, name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('dashboard/', views.citizen_dashboard, name='citizen_dashboard'),
path('report-issue/', views.report_issue, name='report_issue'),
]
+82 -5
View File
@@ -1,17 +1,94 @@
from django.shortcuts import render, redirect
from django.contrib.auth import login
from .forms import CitizenRegistrationForm
from django.contrib import messages
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm
from .models import Issue, IssueCategory
from .forms import CitizenRegistrationForm, IssueForm
def home(request):
return render(request, 'core/index.html')
def home(request):
if request.user.is_authenticated and request.user.is_citizen:
return redirect('citizen_dashboard')
return render(request, 'core/index.html')
def home(request):
if request.user.is_authenticated and request.user.is_citizen:
return redirect('citizen_dashboard')
return render(request, 'core/index.html')
@login_required
def citizen_dashboard(request):
if not request.user.is_citizen:
messages.error(request, 'Access denied. Citizen role required.')
return redirect('home')
# Get only basic data for now
all_user_issues = Issue.objects.filter(reporter=request.user)
user_issues_display = all_user_issues.order_by('-created_at')[:5]
resolved_count = all_user_issues.filter(status='resolved').count()
categories = IssueCategory.objects.all()
context = {
'user_issues': user_issues_display,
'resolved_count': resolved_count,
'categories': categories,
'issue_form': IssueForm(),
}
return render(request, 'core/citizen_dashboard.html', context)
@login_required
def report_issue(request):
if not request.user.is_citizen:
messages.error(request, 'Access denied. Citizen role required.')
return redirect('home')
if request.method == 'POST':
form = IssueForm(request.POST, request.FILES)
if form.is_valid():
issue = form.save(commit=False)
issue.reporter = request.user
issue.save()
messages.success(request, 'Issue reported successfully!')
return redirect('citizen_dashboard')
else:
messages.error(request, 'Please correct the errors below.')
else:
form = IssueForm()
return render(request, 'core/report_issue.html', {'form': form})
def register(request):
if request.method == 'POST':
form = CitizenRegistrationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect('home')
messages.success(request, 'Registration successful! Please login.')
return redirect('login')
else:
form = CitizenRegistrationForm()
return render(request, 'core/register.html', {'form': form})
return render(request, 'core/register.html', {'form': form})
def custom_login(request):
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, f'Welcome back, {username}!')
return redirect('home')
else:
messages.error(request, 'Invalid username or password.')
else:
messages.error(request, 'Invalid username or password.')
else:
form = AuthenticationForm()
return render(request, 'core/login.html', {'form': form})