1.
Install django
pip install django
- Show version of django
python -m django --version
2. Create project
django-admin startproject django_project
3. Run project
python [Link] runserver
4. Create new app
python [Link] startapp blog
- Go to [Link] then import http and create a function
from [Link] import render
from [Link] import HttpResponse
def home(request):
return HttpResponse("<h1>Home page</h1>")
- Create [Link] file inside of blog
from [Link] import path
from . import views
urlpatterns = [
path('',[Link])
]
[Link] of django_project
from [Link] import admin
from [Link] import path, include
urlpatterns = [
path('admin/', [Link]),
path('blog/', include('[Link]'))
]
5. Create template(for html)
- create a folder template inside of blog and inside template add
folder blog (create html files inside that)
- Add that html and before that
- INSTALLED_APPS = [
'[Link]',
And
def about(request):
return render(request,'blog/[Link]')
6. Display a data from post
[Link]
from [Link] import render
from [Link] import HttpResponse
posts = [
{
'author' : 'Habtamu Asayto',
'title' : 'The first post',
'content' : 'The whole content of the first blog post',
'posted_date' : 'February 12, 2024'
},
{
'author' : 'Some One',
'title' : 'The second post',
'content' : 'The whole content of the 2ns blog post',
'posted_date' : 'September 12, 2025'
}
]
def index(request):
context = {
'posts' : posts
}
return render(request, 'blog/[Link]', context)
def about(request):
return render(request,'blog/[Link]',{'title': 'About'})
[Link]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>Django blog {{ title }}</title>
{% else %}
<title>Django blog</title>
{% endif %}
</head>
<body>
{% for post in posts %}
<h1>{{ [Link] }}</h1>
<p>By {{ [Link] }} on {{ post.posted_date }}</p>
<p> {{ [Link] }} </p>
{% endfor %}
</body>
</html>
[Link]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>Django blog - {{ title }}</title>
{% else %}
<title>Django blog</title>
{% endif %}
</head>
<body>
<h1>About page</h1>
</body>
</html>
7. Create a [Link] file used as a parent html file, then index and
about files are inheriting from base
[Link]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>Django blog - {{ title }}</title>
{% else %}
<title>Django blog</title>
{% endif %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
[Link]
{% extends "blog/[Link]" %}
{% block content %}
{% for post in posts %}
<h1>{{ [Link] }}</h1>
<p>By {{ [Link] }} on {{ post.posted_date }}</p>
<p> {{ [Link] }} </p>
{% endfor %}
{% endblock content %}
8. Add bootstrap and css
9. Create admin user
python [Link] createsuperuser
- There error
[Link]: no such table: auth_user
- To fix the above error, migrate
python [Link] makemigrations
python [Link] migrate
10. Database and migration
[Link]
from [Link] import models
from [Link] import timezone
from [Link] import User # many post to one user
relationship between users and the model
class Post([Link]):
title = [Link](max_length=255),
content = [Link](),
posted_date = [Link](default=[Link]),
author = [Link](User, on_delete=[Link])
then,
python [Link] makemigrations blog
python [Link] sqlmigrate blog 0001
python [Link] migrate
python [Link] shell
from [Link] import Post
from [Link] import User
[Link]()
[Link]()
[Link](username='habtamu')
[Link](username='habtamu').first() # assign this to
user variable
user = [Link](username='habtamu').first()
user
[Link] = [Link]
>>> user = [Link](id=1)
>>> user
Now continue to table Post
post_1 = Post(title='Blog Post 1',content='Content of blog post
1',author=user)
post_1.save()
[Link]()
>>> post = [Link]()
>>> [Link]
>>> [Link]
<User: Habtamu>
>>> [Link]
'habtamuasayto360@[Link]'
>>> user.post_set
>>> user.post_set.all()
>>> user.post_set.create(title='Blog Post 3', content='The content
of blog post 3')
>>> [Link]()
Now, display this inserted database to views
[Link]
from .models import Post
def index(request):
context = {
'posts' : [Link]()
}
return render(request, 'blog/[Link]', context)
Date format
[Link]
<small class="text-muted">{{ post.posted_date|date:"F d,
Y" }}</small>
Register the Post blog to [Link]
[Link]
from [Link] import admin
from .models import Post
[Link](Post)
- To add a post inside admin of blog
[Link]
from [Link] import admin
from .models import Post
[Link](Post)
11. Registration form
Create new users
python [Link] startapp users
then, add into INSTALLED_APPS on [Link]
'[Link]',
Go to [Link] and add a function register
[Link]
from [Link] import render, redirect
from [Link] import UserCreationForm
from [Link] import messages
def register(request):
if [Link] == 'POST':
form = UserCreationForm([Link])
if form.is_valid():
[Link]()
username = form.cleaned_data.get('username')
[Link](request,f"Account created for
{username}!")
return redirect('blog-home')
else:
form = UserCreationForm()
return render(request, 'users/[Link]', {'form':form})
[Link]
{% extends "blog/[Link]" %}
{% block content %}
<div class="content-section">
<form method="post">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">
Signup here
</legend>
{{ form.as_p }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info"
type="submit">Signup</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">Aready have account <a
href="#" class="ml-2">SignIn</a></small>
</div>
</div>
{% endblock content %}
Main [Link]
from [Link] import admin
from [Link] import path, include
from users import views as user_views
urlpatterns = [
path('admin/', [Link]),
path('register/', user_views.register, name='register'),
path('blog/', include('[Link]')),
]
[Link] inside of blog
<div class="col-md-8">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{[Link]}}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% block content %}
{% endblock %}
</div>
The above one has only username and password, to add other attribute
- Create [Link] insides of users app
from django import forms
from [Link] import User
from [Link] import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = [Link]()
class Meta:
model = User
fields = ['username','email','password1','password2']
and change [Link]
from [Link] import render, redirect
from [Link] import messages
from .forms import UserRegisterForm
def register(request):
if [Link] == 'POST':
form = UserRegisterForm([Link])
if form.is_valid():
[Link]()
username = form.cleaned_data.get('username')
[Link](request,f"Account created for
{username}!")
return redirect('blog-home')
else:
form = UserRegisterForm()
return render(request, 'users/[Link]', {'form':form})
12. Crispy form (to create awesome from in bootstrap)
- Install it
pip install django-crispy-forms
pip install crispy-bootstrap4
- Go to setting
'crispy_forms',
'crispy_bootstrap4',
CRISPY_TEMPLATE_PACK = 'bootstrap4'
- Load it above [Link]
{% load crispy_forms_tags %}
{{ form|crispy }}
13. Login and Logout
- Import auth_views on [Link]
from [Link] import views as auth_views
path('login/',auth_views.LoginView.as_view(template_name='users/[Link]'
), name='login'),
path('logout/',auth_views.LogoutView.as_view(template_name='users/
[Link]'), name='logout'),
- Create [Link] inside users template
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> Login
</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info"
type="submit">Login</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">Haven't an account ? <a
href="{% url 'register' %}" class="ml-2">Signup Here</a></small>
</div>
</div>
{% endblock content %}
- Add redirect at the end of [Link]
LOGIN_REDIRECT_URL = 'blog-home'
[Link]
{% extends "blog/[Link]" %}
{% block content %}
<h2>You have logged out</h2>
<div class="border-top pt-3">
<small class="text-muted">
<a href="{% url 'login' %}" class="ml-2">Sign in</a>
</small>
</div>
{% endblock content %}
[Link]
<div class="navbar-nav">
{% if user.is_authenticated %}
<a class="nav-item nav-link" href="{% url 'logout'
%}">Logout</a>
{% else %}
<a class="nav-item nav-link" href="{% url 'login'
%}">Login</a>
<a class="nav-item nav-link" href="{% url 'register'
%}">Register</a>
{% endif %}
</div>
- Add profile function inside of users [Link]
def profile(request):
return render(request, 'users/[Link]')
[Link] inside template
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<h2>{{ [Link] }}</h2>
{% endblock content %}
[Link]
path('profile/', user_views.profile, name='profile'),
[Link]
<div class="navbar-nav">
{% if user.is_authenticated %}
<a class="nav-item nav-link" href="{% url 'profile' %}">Profile</a>
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
{% else %}
<a class="nav-item nav-link" href="{% url 'login' %}">Login</a>
<a class="nav-item nav-link" href="{% url 'register' %}">Register</a>
{% endif %}
</div>
- Login required pages
[Link] of users
from [Link] import login_required
@login_required
def profile(request):
return render(request, 'users/[Link]')
[Link]
LOGIN_URL = 'login'
14. Profile
[Link]
from [Link] import models
from [Link] import User
class Profile([Link]):
user = [Link](User, on_delete=[Link])
image =
[Link](default='[Link]',upload_to='profile_pics')
def __str__(self):
return f'{[Link]} Profile'
To migrate Models
python [Link] makemigrations
python -m pip install Pillow
python [Link] makemigrations
python [Link] migrate
To compile locale
python [Link] makemessages
python [Link] complilemessages
[Link] inside users, to add Admin page
from [Link] import admin
from .models import Profile
[Link](Profile)
- Access Profile attribute on the views
python [Link] shell
>>> from [Link] import User
>>> [Link]()
>>> user = [Link](username='Habtamu').first()
>>> [Link]
profile_pics directory inside the project is created
- Change the path of media on [Link], then I will store profile
pictures == media/profile_pics path
MEDIA_ROOT = [Link](BASE_DIR, 'media') # to access the media
from our pc on browser
MEDIA_URL = '/media/'
- To display profile info on the view
[Link]
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img"
src="{{ [Link] }}">
<div class="media-body">
<h2 class="account-heading">{{ [Link] }}</h2>
<p class="text-secondary">{{ [Link] }} </p>
</div>
</div>
</div>
{% endblock content %}
- To display profile image, we must fix on [Link]
from [Link] import settings
from [Link] import static
if [Link]:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
- Create [Link] file on users folder
from [Link] import post_save
from [Link] import User
from [Link] import receiver
from .models import Profile
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
[Link](user=instance)
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
[Link]()
[Link] on users folder
def ready(self):
import [Link]
15. Update User profile
- Inside [Link]
from .models import Profile
class UserUpdateForm([Link]):
email = [Link]()
class Meta:
model = User
fields = ['username', 'email']
class ProfileUpdateForm([Link]):
class Meta:
model = Profile
fields = ['image']
[Link]
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
@login_required
def profile(request):
u_form = UserUpdateForm()
p_form = ProfileUpdateForm()
context = {
'u_form': u_form,
'p_form' : p_form
}
return render(request, 'users/[Link]' , context)
[Link]
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img style="width:70px;height:70px;margin-right:7px"
class="rounded-circle account-img" src="{{ [Link] }}" />
<div class="media-body">
<h2 class="account-heading">{{ [Link] }}</h2>
<p class="text-secondary">{{ [Link] }} </p>
</div>
</div>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Profile
information</legend>
{{ u_form|crispy }}
{{ p_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info"
type="submit">Update</button>
</div>
</form>
</div>
{% endblock content %}
On [Link]
Add instance based on POST or not
from [Link] import render, redirect
from [Link] import messages
from [Link] import login_required
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
def register(request):
if [Link] == 'POST':
form = UserRegisterForm([Link])
if form.is_valid():
[Link]()
username = form.cleaned_data.get('username')
[Link](request,f"{username} Your account are created
successfully, Login now !")
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/[Link]', {'form':form})
@login_required
def profile(request):
if [Link] == 'POST':
u_form = UserUpdateForm([Link], instance = [Link])
p_form = ProfileUpdateForm([Link], [Link], instance =
[Link])
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
[Link](request, f"Your account has updated
successfully !")
return redirect('profile')
else:
u_form = UserUpdateForm(instance = [Link])
p_form = ProfileUpdateForm(instance = [Link])
context = {
'u_form': u_form,
'p_form' : p_form
}
return render(request, 'users/[Link]', context)
- Resize image size
[Link]
from [Link] import models
from [Link] import User
from PIL import Image
class Profile([Link]):
user = [Link](User, on_delete=[Link])
image =
[Link](default='[Link]',upload_to='profile_pics')
def __str__(self):
return f'{[Link]} Profile'
def save(self):
super().save()
img = [Link]([Link])
if [Link] > 300 or [Link] > 300:
output_size = (300, 300)
[Link](output_size)
[Link]([Link])
- Add image on the home page of each cards
[Link]
<img style="width:80px;height:80px;margin-right:7px" class="rounded-circle
article-img" src="{{ [Link] }}"/>
16. CRUD
- Create Create, Display, Update and Delete functions on blog
[Link]
from [Link] import ListView
Display
class PostListView(ListView):
model = Post
template_name='blog/[Link]'
context_object_name = 'posts'
ordering = ['-posted_date'] # Display based on the date
[Link] on blog
from [Link] import path
from .views import PostListView
from . import views
urlpatterns = [
#path('',[Link], name='blog-home'),
path('',PostListView.as_view(), name='blog-home'),
path('about/',[Link], name='blog-about')
]
- To create Detail View
[Link]
from [Link] import ListView, DetailView
path('post/<int:pk>/',PostDetailView.as_view(), name='post-detail'),
create post_detail.html on blog template
{% extends "blog/[Link]" %}
{% block content %}
<div class="card" style="margin-top: 19px;">
<h5 class="card-header">
<div class="article-metadata">
<img style="width:80px;height:80px;margin-right:7px"
class="rounded-circle article-img"
src="{{ [Link] }}"/>
<a class="mr-2" href="#">{{ [Link] }}</a>
<small class="text-muted">{{ object.posted_date|date:"F
d, Y" }}</small>
</div>
</h5>
<div class="card-body">
<h3><a class="article-title" href="#">{{ [Link] }}</a>
</h3>
<p class="article-content">{{ [Link] }}</p>
</div>
</div>
{% endblock content %}
- Go to Post detail page when we press one Post
[Link]
<h3><a class="article-title" href="{% url 'post-detail' [Link]
%}">{{ [Link] }}</a> </h3>
- Create New post on View (inside of blog app)
[Link]
from [Link] import ListView, DetailView, CreateView
class PostCreateView(CreateView):
model = Post
fields = ['title', 'content']
[Link]
from .views import PostListView, PostDetailView, PostCreateView
- Create post_form.html file inside blog template
Post_form.html
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">
Create Blog post
</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info"
type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
- When we run, fill and submit the project, then NOT NULL constraint
failed:, so we must add on [Link]
[Link]
class PostCreateView(CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self,form):
[Link] = [Link]
return super().form_valid(form)
[Link] on blog
from [Link] import reverse
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': [Link]})
- Now it create new post and redirect to its own created post
- Another way to redirect post/new to login page if not logged
[Link]
from [Link] import LoginRequiredMixin # redirect to
login
class PostCreateView(LoginRequiredMixin, CreateView):
- Update
[Link]
from [Link] import ListView, DetailView, CreateView,
UpdateView
#Update
class PostUpdateView(LoginRequiredMixin, UpdateView):
model = Post
fields = ['title', 'content']
def form_valid(self,form):
[Link] = [Link]
return super().form_valid(form)
[Link]
from .views import PostListView, PostDetailView, PostCreateView,
PostUpdateView
path('post/<int:pk>/update',PostUpdateView.as_view(), name='post-update'),
- Delete a post
[Link]
from [Link] import ListView, DetailView, CreateView,
UpdateView, DeleteView
#Delete
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
def test_func(self):
post = self.get_object()
if [Link] == [Link]:
return True
return False
[Link]
from .views import PostListView, PostDetailView, PostCreateView,
PostUpdateView, PostDeleteView
path('post/<int:pk>/delete',PostDeleteView.as_view(), name='post-delete'),
- Confirm delete, Create delete_confirm.html
Post_delete_confirm.html
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">
Delete Post
</legend>
<h2>Are your sure to delete post "{{ [Link] }}"? </h2>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-danger"
type="submit">Delele</button>
<a class="btn btn-outline-secondary" href="{% url 'post-
detail' [Link] %}">Cancel</a>
</div>
</form>
</div>
{% endblock content %}
- To get success_url
[Link], inside of PostDeleteView function
success_url = '/blog/'
[Link]
<a class="nav-item nav-link" href="{% url 'post-create' %}">New Post</a>
<a class="nav-item nav-link" href="{% url 'profile' %}">Profile</a>
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
Post_detail.html
{% if [Link] == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-
update' [Link] %}"> Update </a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-
delete' [Link] %}"> Delete </a>
</div>
{% endif %}
17. Pagination
- Create [Link] file on and go to shell
>>> from [Link] import Paginator
>>> posts = ['1','2','3','4','5']
>>> p = Paginator(posts,2)
>>> p.num_pages
>>> for page in p.page_range:
... print(page)
...
1
2
3
>>>
>>>
>>> p1= [Link](1)
>>> p1
>>> [Link]
>>> p1.object_list
>>> p1.has_previous()
>>> p1.has_next()
[Link]
Add on PostListView Function
paginate_by = 2
at the end of [Link] on blog
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page=1">First</a>
<a class="btn btn-outline-info mb-4" href="?
page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?
page={{ num }}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num < [Link]|
add:'3' %}
<a class="btn btn-outline-info mb-4" href="?
page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?
page={{ page_obj.next_page_number }}">Next</a>
<a class="btn btn-outline-info mb-4" href="?
page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}
[Link] for cruding users
from [Link] import render, get_object_or_404
from [Link] import User
#Display Users
class UserPostListView(LoginRequiredMixin, ListView):
model = Post
template_name='blog/user_post.html'
context_object_name = 'posts'
ordering = ['-posted_date'] # Display based on the date
paginate_by = 2
def get_queryset(self):
user=get_object_or_404(User, username=[Link]('username'))
return [Link](author=user).order_by('-posted_date')
Create user_post.html
{% extends "blog/[Link]" %}
{% block content %}
<h2 class="mb-3">Posts by {{ [Link] }}
({{ page_obj.[Link] }})</h2>
{% for post in posts %}
<div class="card" style="margin-top: 19px;">
<h5 class="card-header">
<div class="article-metadata">
<img style="width:80px;height:80px;margin-
right:7px" class="rounded-circle article-img"
src="{{ [Link] }}"/>
<a class="mr-2" href="{% url 'user-posts'
[Link] %}">{{ [Link] }}</a>
<small class="text-muted">{{ post.posted_date|
date:"F d, Y" }}</small>
</div>
</h5>
<div class="card-body">
<h3><a class="article-title" href="{% url 'post-detail'
[Link] %}">{{ [Link] }}</a> </h3>
<p class="article-content">{{ [Link] }}</p>
</div>
</div>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page=1">First</a>
<a class="btn btn-outline-info mb-4" href="?
page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?
page={{ num }}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num <
[Link]|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?
page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?
page={{ page_obj.next_page_number }}">Next</a>
<a class="btn btn-outline-info mb-4" href="?
page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}
{% endblock content %}
[Link]
<a class="mr-2" href="{% url 'user-posts' [Link]
%}">{{ [Link] }}</a>
[Link]
from .views import PostListView, PostDetailView, PostCreateView,
PostUpdateView, PostDeleteView, UserPostListView
path('user/<username>',UserPostListView.as_view(), name='user-posts'),
18. Email and password reset
Go to project url
[Link]
path('password-reset/',
auth_views.PasswordResetView.as_view(template_name='users/password_reset.ht
ml'), name='password_reset'),
create password_reset.html inside users app
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Reset Password</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Request
Password Reset</button>
</div>
</form>
</div>
{% endblock content %}
Password_reset_confirm.html
{% extends "blog/[Link]" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Reset Password</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Reset
Password</button>
</div>
</form>
</div>
{% endblock content %}
Password_reset_done.html
{% extends "blog/[Link]" %}
{% block content %}
<div class="alert alert-info">
An email has been sent with instructions to reset your password
</div>
{% endblock content %}
And on [Link]
path('password-reset/done/',
auth_views.PasswordResetDoneView.as_view(template_name='users/password_rese
t_done.html'),name='password_reset_done'),
Then, it needs confirm, so create password_reset_complete.html file
{% extends "blog/[Link]" %}
{% block content %}
<div class="alert alert-info">
Your password has been set.
</div>
<a href="{% url 'login' %}">Sign In Here</a>
{% endblock content %}
[Link]
path('password-reset/',
auth_views.PasswordResetView.as_view(
template_name='users/password_reset.html'
),
name='password_reset'),
path('password-reset/done/',
auth_views.PasswordResetDoneView.as_view(
template_name='users/password_reset_done.html'
),
name='password_reset_done'),
path('password-reset-confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(
template_name='users/password_reset_confirm.html'
),
name='password_reset_confirm'),
path('password-reset-complete/',
auth_views.PasswordResetCompleteView.as_view(
template_name='users/password_reset_complete.html'
),
name='password_reset_complete'),
go to setting
EMAIL_BACKEND = '[Link]'
EMAIL_HOST = '[Link]'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'habtamuasayto360@[Link]'
EMAIL_HOST_PASSWORD = 'mhlqxbcabxepcxht' # this password is generated on my
gmail
- There are some processes on gmail
Enhance safe browsing should on, must 2 step verification and app
password
19. Custom domain name for applicartion
- Find [Link] , but it is not free
20. Enable Https
- Go to [Link]
21. Multi language in django
- Activate virtual
py -m venv venv
- Install django
pip install django
- Create app
python [Link] startapp setting
22. Model translation
pip install django-modeltranslation
[Link]
USE_L10N = True