STAY INFORMED
following content serves as a personal note and may lack complete accuracy or
certainty.
Minimal-Mistakes instruction
Useful vscode Shortcut Keys
Unix Commands
npm Commands
Vim Commands
Git Note
Useful Figma Shortcut Keys
E-Commerce Website Project_1
Setup
mkdir e-commerce-project
cd e-commerce-project
pyenv virtualenv 3.7.13 django_ecommerce_env
pip3 install django==2.2
pyenv local django_ecommerce_env
django-admin startproject ecommerce_project
cd ecommerce_project
python manage.py startapp ecommerce
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'ecommerce',
]
Pages
we need pages for
- index(homepage)
- sign in
- sign up
- user profile
- item list
- item detail
Since sign in, sign up pages already exist, I will just change urls.py in project directory and create the rest.
The file structure should be
ecommerce_project/
ecommerce/
static/
ecommerce/
favicon/
favicon.svg
assets/
...
styles/
style.css
...
templates/
ecommerce/
index.html
...
ecommerce_base/
base.html
...
I simply made base.html
{% load static %}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<link
rel="shortcut icon"
type="image/png"
href="{% static 'ecommerce/favicon/favicon.svg' %}"
/>
<title>{% block title %}Coplate{% endblock title %}</title>
</head>
<body>
{% block header %}{% endblock header %} {% block content %}{% endblock
content %} {% block footer %}{% endblock footer %}
</body>
</html>
and index.html
{% extends "ecommerce_base/base.html" %} {% block content %}
<h1>hi</h1>
{% endblock content %}
To render the page,
# urls.py in project dir
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
# admin
path('admin/', admin.site.urls),
# ecommerce
path('', include("ecommerce.urls")),
# allauth
path('', include("allauth.urls")), # for sign in, sign up, etc
]
# urls.py in ecommerce
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name='index')
]
# views.py
from django.shortcuts import render
def index(request):
return render(request, "ecommerce/index.html")
Now I see index, login pages.
Create User
Create User Model
For user model, I will use AbstractUser module which offers basic user model schema, so User model inherits AbstractUser and you need to add ‘AUTH_USER_MODEL = “[app-name].User”` to settings.py at very bottom.
# models. py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
nickname = models.CharField(max_length=15, unique=True) # additional schema
def __str__(self):
return self.nickname
and register User model to admin page.
# admin.py
from django.contrib import admin
from .models import User
from django.contrib.auth.admin import UserAdmin
admin.site.register(User, UserAdmin)
UserAdmin includes all necessary fields and functionalities, like handling permissions and user information.
Create Super User
To check User model is successfully registered, create superuser.
python manage.py createsuperuser
# type your info
and go to /admin and check it.
allauth
Setup
django-allauth is a Django application that provides comprehensive user authentication, registration, and account management functionalities. It simplifies the integration of user authentication and social account logins into your Django project.
pip install django-allauth
# settings.py
INSTALLED_APPS = [
...
'ecommerce',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
]
SITE_ID = 1
...
MIDDLEWARE = [
...
'allauth.account.middleware.AccountMiddleware',
...
]
...
# Auth settings
AUTHENTICATION_BACKENDS = [
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by email
'allauth.account.auth_backends.AuthenticationBackend',
]
# Email settings
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
And migrate it
python manage.py migrate
Handling sign up
When user sign up successfully, it redirect to account/profile, which I haven’t made the page, so it will give 404 error. I don’t need to page, and just add some code to settings.py.
# settings.py
...
# redirect to index page when signup successfully
ACCOUNT_SIGNUP_REDIRECT_URL = "index"
LOGIN_REDIRECT_URL = "index"
I will add some more.
ACCOUNT_LOGOUT_ON_GET = True # not redirect to logout page
ACCOUNT_AUTHENTICATION_METHOD = "email" # require email when login instead of username
ACCOUNT_EMAIL_REQUIRED = True # Email is required when sign up
ACCOUNT_USERNAME_REQUIRED = False # username field is gone on sign up form
ACCOUNT_SESSION_REMEMBER = True # browser remember user depending on the line below
SESSION_COOKIE_AGE = 3600 # default is 2 weeks
Also, since I added nickname field in user model, I will make signup form.
# forms.py
from django import forms
from .models import User
class SignupForm(forms.ModelForm):
class Meta:
model = User
fields = ["nickname"]
def signup(self, request, user):
user.nickname = self.cleaned_data["nickname"]
user.save()
and add this line in settings.py to apply signup form.
# settings.py
ACCOUNT_SIGNUP_FORM_CLASS = "ecommerce.forms.SignupForm" # use SignupForm in forms.py instead
Account email verification
# settings.py
ACCOUNT_EMAIL_VERIFICATION = "mandatory" # user cannot login until verify email
ACCOUNT_CONFIRM_EMAIL_ON_GET = True # redirect to login page
# redirect to account_email_confirmation_done page
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = "account_email_confirmation_done"
ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL = "account_email_confirmation_done"
and add a path for confirmation page in urls.py in project dir.
from django.views.generic import TemplateView
urlpatterns = [
# admin
path('admin/', admin.site.urls),
# ecommerce
path('', include("ecommerce.urls")),
# allauth
path(
"email-confirmation-done/",
TemplateView.as_view(template_name="ecommerce/email.confirmation_done.html"),
name="account_email_confirmation_done"),
path('', include("allauth.urls")), # for sign in, sign up, etc
]
Now I need to create a template for confirmation.
Email Confirmed.
<a href="{% url 'account_login'%}">go to login</a>
When user signup, user will get a link and if user click the link, it redirects to this page and email is confirmed.
Handling password
- when change password before sign in(forgot password)
Just simply add this line in settings.py
# settings.py
PASSWORD_RESET_TIMEOUT = 600 # Sets the number of seconds a password reset link remains valid.
- when change password after sign in I added a link to change password in index.html
<a href="{% url 'account_change_password' %}">change password</a>
and create view class for password change view.
# views. py
from django.urls import reverse
from allauth.account.views import PasswordChangeView
class CustomPasswordChangeView(PasswordChangeView):
def get_success_url(self):
return reverse("index")
and add path for this.
# project/urls.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic import TemplateView
from ecommerce.views import CustomPasswordChangeView
urlpatterns = [
...
# allauth
path(
"email-confirmation-done/",
TemplateView.as_view(template_name="ecommerce/email.confirmation_done.html"),
name="account_email_confirmation_done"),
path('password/change/',
CustomPasswordChangeView.as_view(),
name="account_password_change",
),
path('', include("allauth.urls")), # for sign in, sign up, etc
]
Clear session
This is clear session command. Need to make auto-system to execute this.
python manage.py clearsessions
Learned New
Since I created user(including superuser) before I make a User model which has nickname field, the user accounts don’t have a nickname. To fix this issue, make nickname field accepts null,
# models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
nickname = models.CharField(max_length=15, unique=True, null=True)
def __str__(self):
return self.email
and add this line so that admin page will display nickname field.
# admin.py
UserAdmin.fieldsets += (("Custom fields", {"fields": ("nickname", )}), )
Now you can define nickname.