Django app development

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

Leave a Comment

Your email address will not be published. Required fields are marked *