Работа с формами
Работа с формами в официальном руководстве для Django 2:
Добавление классов и атрибутов к ModelForm.
Если нужно навесить классы или изменить атрибуты для рендеринга полей формы, использующей ModelForm, то проще всего переопределить __init__.
class CommentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.fields['name'].widget.attrs.update({'class': 'special'})
    self.fields['comment'].widget.attrs.update(size='40')
В некоторых случаях вместо определённой, заданной заранее формы удобнее создавать формы для изменения и создания новых моделей "на лету", используя паттерн "фабрика":
from django.forms import Textarea
Form = modelform_factory(Book, form=BookForm,
             widgets={"title": Textarea()})
- ModelForm factory function - страница в официальном руководстве.
 - Работа с формами на https://developer.mozilla.org - статья из руководства на русском.
 - Django example: creating a custom form field widget - полезная статья на Medium с примером создания кастомного виджета для формы.
 
Валидация datetime в классе формы
import datetime
def clean_datetime(self):
    d = self.cleaned_data['datetime']
    # для корректного сравнения и избежании ошибки, убираем временную зону
    d = d.replace(tzinfo=None)
    now = datetime.datetime.now()
    if d < now:
        raise ValidationError('Недопустимое значение! Дата события не может быть уже прошедшей.')
    if d > now + datetime.timedelta(days=365):
        raise ValidationError('Недопустимое значение! Дата планируемого события не может быть задана больше, '
                              'чем на год вперёд от настоящего времени.')
    return d
AJAX
- How to Work With AJAX Request With Django - статья с простым примером работы с ajax для форм в django.
 - Компонент django-ajax
 - Полезные ссылки
 - Cross Site Request Forgery protection
 - О передаче данных постом при аякс-запросе - ответ на qaru с примерами реализации
 
Работа с redis
# Зайти в redis:
redis-cli
# Выбрать базу, отличную от 0
select 2
# Посмотреть все сохранённые ключи:
keys *
# Delete all data in cache:
flushall
# Show size of data:
size
# Проверить работу redis и базы:
ping # pong
Декораторы для View
Про декораторы в Python:
- Decorators, статья - https://python-3-patterns-idioms-test.readthedocs.io
 - Writing view decorators for Django - статья на https://passingcuriosity.com
 - 5 reasons you need to learn to write Python decorators
 - Custom Decorators To Check User Roles And Permissions In Django
 - Working with Django View Decorators
 - Decorators With Arguments in Python
 
Пример кастомного декоратора, проверяющего, что запрос совершён с помощью ajax и метода post:
from django.core.exceptions import PermissionDenied
def allow_post_ajax(func):
    """
    Декоратор, разрешающий действия только c помощью ajax и post-запросов
    :param func:
    :return: func
    """
    def wrap(request, *args, **kwargs):
        if request.is_ajax() and request.method == 'POST':
            return func(request, *args, **kwargs)
        else:
            raise PermissionDenied
   return wrap
Кастомный декоратор с передачей аргументов в функцию:
def wrap_in_a(tag):
   """
   Wrap the result of a function in a `tag` HTML tag.
   """
   def _dec(func):
       def _new_func(*args, **kwargs):
           return "<%s>%s</%s>" % (tag, func(*args, **kwargs), tag)
       return _new_func
   return _dec
@wrap_in_a('div')
@login_required
def my_name(request):
    return request.user.first_name