timezone setup on web server
### List timezones
timedatectl list-timezones
### Set timezone e.g. Singapore
sudo timedatectl set-timezone Asia/Singapore
### Verify changes
timedatectl
date
Install django on venv
$ source venv/bin/active (venv) $ pip install django
(venv) $ pip install django-crispy-forms
(venv) $ pip install Pillow
(venv) $ python -m pip install Pillow (venv) $ django-admin startproject domain.sg (venv) # python manage.py startapp blog
(venv) # python manage.py startapp users
### Test run your project (venv) $ python manage.py runserver 0.0.0.0:8888
settings.py
ALLOWED_HOSTS = ['*']
TIME_ZONE = 'Asia/Singapore'
USE_TZ = False
STATIC_ROOT = os.path.join(BASE_DIR, '../static')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, '../media')
MEDIA_URL = '/media/'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/path/to/mysql.cnf',
},
}
}
INSTALLED_APPS = [
'blog.apps.BlogConfig',
'users.apps.UsersConfig',
'crispy_forms',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
CRISPY_TEMPLATE_PACK = 'bootstrap4'
urls.py (main)
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path, include
urlpatterns = [
...
path('admin/', admin.site.urls),
path('register/', users_views.register, name='register'),
path('profile/', users_views.profile, name='profile'),
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
path('', include('blog.urls')),
path('blog/', include('blog.urls')),
path('polls/', include('polls.urls')),
...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
setting.py (customization)
LOGIN_REDIRECT_URL = 'blog-home'
LOGIN_URL = 'login'
mysql.cnf
### Setup mysql.cnf
sudo nano mysql.cnf
[client]
database = 'dbname'
user = 'username'
password = 'password'
default-character-set = 'utf8'
Django Databases Constant:
### WORKING ### DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'OPTIONS': { 'read_default_file': os.path.join(BASE_DIR, 'mysql_secret.cnf'), } } } ### SAMPLE ### DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'OPTIONS': { 'read_default_file': '/tutorial/auth/mysql.cnf', }, } }
Register model to its admin.py (to able to manage from admin portal)
### Example Post
# Register your models here.
from .models import Post
admin.site.register(Post)
### Example Users
# Register your models here.
from .models import Profile
admin.site.register(Profile)
{{ form.as_p}} on templates. (crispy is better)
<form method="post">
...
{% csrf_token %}
{{ form.as_p }}
...
</form>
crispy for templates html
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form | crispy }}
</form>
{% endblock content %}
Jinja
{% if user.is_authenticated %}
<a class="nav-item nav-link" href="/logout">Logout</a>
{% else %}
<a class="nav-item nav-link" href="/login">Login</a>
<a class="nav-item nav-link" href="/register">Register</a>
{% endif %}
Common decorators (login_required)
from django.contrib.auth.decorators import login_required
@login_required()
def profile(request):
Common decorators (receiver)
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from .models import Profile
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
views.py messages
from django.contrib import messages
messages.debug
messages.info
messages.success
messages.warning
messages.error
Pagination
class PostListView(ListView):
model = models.Post
template_name = 'blog/home.html'
context_object_name = 'posts'
paginate_by = 2
signals.py (each app)
E.g. When new user is created, create profile too.
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
# When User is created, send this signal
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
# When User is saved, send this signal
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
apps.py (each app e.g. users)
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
Frequently used commands
### Create superuser
(venv) python manage.py makemigrations
(venv) python manage.py migrate
(venv) python manage.py createsuperuser
### Generate requirements.txt
(venv) pip freeze > requirements.txt
### Check SQL statement
(venv) python manage.py sqlmigrate blog 0001
### shell
(venv) python manage.py shell
migrate
### Force re-run migration
manage.py migrate --fake customer zero
migrate customer
Frequently used shell commands
>>> from blog.models import Post
>>> from django.contrib.auth.models import User
>>> User.objects.all()
>>> User.objects.first()
>>> User.objects.filter(username='test')
>>> User.objects.filter(username='test').first()
>>> user = User.objects.filter(username='test').first()
>>> user.id
>>> user.pk
>>> Post.objects.all()
>>> post1 = Post(title='Blog 1', content='contentxyz', author=user)
>>> post1.save()
>>> Post.objects.all()
>>> post2 = Post(title='Title2', content='Second post', author_id=user.id)
>>> post2.save()
>>> user.post_set.all()
>>> user.post_set.all().first()
>>> user.post_set.create(title='Title3', content='Content3')
>>> from django.contrib.auth.models import User
>>> user = User.objects.filter(username='kim').first()
>>> user.profile.image
>>> user.profile.image.url
>>> user.profile.image.width
>>> user.profile.image.height
Pagination (learing)
### Example 2 post per page
from django.core.paginator import Paginator
posts = ['1', '2', '3', '4', '5']
p = Paginator(posts, 2)
### How many pages
p.num_pages
### Loop the pages
for page in p.page_range:
print(page)
### Access page 1
p1 = p.page(1)
### Get page number
p1. number
### Access to the objects in the page 1
p1.object_list
### Check if has previous or next page
p1.has_previous()
p1.has_next()
### Get the page number of next page
p1.next_page_number()
Create model from an existing database table
### view on terminal
$ python manage.py inspectdb
### Output to file
$ python manage.py inspectdb > models.py