\documentclass[10pt,a4paper]{article} % Packages \usepackage{fancyhdr} % For header and footer \usepackage{multicol} % Allows multicols in tables \usepackage{tabularx} % Intelligent column widths \usepackage{tabulary} % Used in header and footer \usepackage{hhline} % Border under tables \usepackage{graphicx} % For images \usepackage{xcolor} % For hex colours %\usepackage[utf8x]{inputenc} % For unicode character support \usepackage[T1]{fontenc} % Without this we get weird character replacements \usepackage{colortbl} % For coloured tables \usepackage{setspace} % For line height \usepackage{lastpage} % Needed for total page number \usepackage{seqsplit} % Splits long words. %\usepackage{opensans} % Can't make this work so far. Shame. Would be lovely. \usepackage[normalem]{ulem} % For underlining links % Most of the following are not required for the majority % of cheat sheets but are needed for some symbol support. \usepackage{amsmath} % Symbols \usepackage{MnSymbol} % Symbols \usepackage{wasysym} % Symbols %\usepackage[english,german,french,spanish,italian]{babel} % Languages % Document Info \author{Olivier R. (OGR)} \pdfinfo{ /Title (django.pdf) /Creator (Cheatography) /Author (Olivier R. (OGR)) /Subject (Django Cheat Sheet) } % Lengths and widths \addtolength{\textwidth}{6cm} \addtolength{\textheight}{-1cm} \addtolength{\hoffset}{-3cm} \addtolength{\voffset}{-2cm} \setlength{\tabcolsep}{0.2cm} % Space between columns \setlength{\headsep}{-12pt} % Reduce space between header and content \setlength{\headheight}{85pt} % If less, LaTeX automatically increases it \renewcommand{\footrulewidth}{0pt} % Remove footer line \renewcommand{\headrulewidth}{0pt} % Remove header line \renewcommand{\seqinsert}{\ifmmode\allowbreak\else\-\fi} % Hyphens in seqsplit % This two commands together give roughly % the right line height in the tables \renewcommand{\arraystretch}{1.3} \onehalfspacing % Commands \newcommand{\SetRowColor}[1]{\noalign{\gdef\RowColorName{#1}}\rowcolor{\RowColorName}} % Shortcut for row colour \newcommand{\mymulticolumn}[3]{\multicolumn{#1}{>{\columncolor{\RowColorName}}#2}{#3}} % For coloured multi-cols \newcolumntype{x}[1]{>{\raggedright}p{#1}} % New column types for ragged-right paragraph columns \newcommand{\tn}{\tabularnewline} % Required as custom column type in use % Font and Colours \definecolor{HeadBackground}{HTML}{333333} \definecolor{FootBackground}{HTML}{666666} \definecolor{TextColor}{HTML}{333333} \definecolor{DarkBackground}{HTML}{08A36A} \definecolor{LightBackground}{HTML}{EFF9F5} \renewcommand{\familydefault}{\sfdefault} \color{TextColor} % Header and Footer \pagestyle{fancy} \fancyhead{} % Set header to blank \fancyfoot{} % Set footer to blank \fancyhead[L]{ \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{C} \SetRowColor{DarkBackground} \vspace{-7pt} {\parbox{\dimexpr\textwidth-2\fboxsep\relax}{\noindent \hspace*{-6pt}\includegraphics[width=5.8cm]{/web/www.cheatography.com/public/images/cheatography_logo.pdf}} } \end{tabulary} \columnbreak \begin{tabulary}{11cm}{L} \vspace{-2pt}\large{\bf{\textcolor{DarkBackground}{\textrm{Django Cheat Sheet}}}} \\ \normalsize{by \textcolor{DarkBackground}{Olivier R. (OGR)} via \textcolor{DarkBackground}{\uline{cheatography.com/143343/cs/30794/}}} \end{tabulary} \end{multicols}} \fancyfoot[L]{ \footnotesize \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{LL} \SetRowColor{FootBackground} \mymulticolumn{2}{p{5.377cm}}{\bf\textcolor{white}{Cheatographer}} \\ \vspace{-2pt}Olivier R. (OGR) \\ \uline{cheatography.com/ogr} \\ \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Cheat Sheet}} \\ \vspace{-2pt}Published 6th February, 2022.\\ Updated 12th February, 2022.\\ Page {\thepage} of \pageref{LastPage}. \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Sponsor}} \\ \SetRowColor{white} \vspace{-5pt} %\includegraphics[width=48px,height=48px]{dave.jpeg} Measure your website readability!\\ www.readability-score.com \end{tabulary} \end{multicols}} \begin{document} \raggedright \raggedcolumns % Set font size to small. Switch to any value % from this page to resize cheat sheet text: % www.emerson.emory.edu/services/latex/latex_169.html \footnotesize % Small font. \begin{tabularx}{17.67cm}{x{7.7715 cm} x{9.4985 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Preparing environnement}} \tn % Row 0 \SetRowColor{LightBackground} `mkdir project\_name \&\& cd \$\_` & Create project folder and navigate to it \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} `python -m venv env\_name` & Create venv for the project \tn % Row Count 4 (+ 2) % Row 2 \SetRowColor{LightBackground} `source env\_name\textbackslash{}bin\textbackslash{}activate` & Activate environnement (Replace "bin" by "Scripts" in Windows) \tn % Row Count 7 (+ 3) % Row 3 \SetRowColor{white} `pip install django` & Install Django (and others dependencies if needed) \tn % Row Count 10 (+ 3) % Row 4 \SetRowColor{LightBackground} `pip freeze \textgreater{} requirements.txt` & Create requirements file \tn % Row Count 12 (+ 2) % Row 5 \SetRowColor{white} `pip install -r requirements.txt` & Install all required files based on your pip freeze command \tn % Row Count 15 (+ 3) % Row 6 \SetRowColor{LightBackground} `git init` & Version control initialisation, be sure to create appropriate \{\{link="https://djangowaves.com/tips-tricks/gitignore-for-a-django-project/"\}\}gitignore\{\{/link\}\} \tn % Row Count 23 (+ 8) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Create project}} \tn % Row 0 \SetRowColor{LightBackground} `django-admin startproject mysite (or I like to call it config)` & This will create a mysite directory in your current directory the manage.py file \tn % Row Count 4 (+ 4) % Row 1 \SetRowColor{white} `python manage.py runserver` & You can check that everything went fine \tn % Row Count 6 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Database Setup}} \tn % Row 0 \SetRowColor{LightBackground} Open up \seqsplit{`mysite/settings.py`} & It's a normal Python module with module-level variables representing Django settings. \tn % Row Count 5 (+ 5) % Row 1 \SetRowColor{white} `ENGINE` – \seqsplit{`'django.db.backends.sqlite3'`}, \seqsplit{`'django.db.backends.postgresql'`}, \seqsplit{`'django.db.backends.mysql'`}, or \seqsplit{`'django.db.backends.oracle'`} & If you wish to use another database, install the appropriate database \{\{link="https://docs.djangoproject.com/en/4.0/topics/install/\#database-installation"\}\}bindings\{\{/link\}\} and change the following keys in the DATABASES 'default' item to match your database connection settings \tn % Row Count 19 (+ 14) % Row 2 \SetRowColor{LightBackground} `NAME` – The name of your database. If you're using SQLite, the database will be a file on your computer; in that case, NAME should be the full absolute path, including filename, of that file. & The default value, `BASE\_DIR / 'db.sqlite3'`, will store the file in your project directory. \tn % Row Count 29 (+ 10) % Row 3 \SetRowColor{white} If you are not using SQLite as your database, additional settings such as `USER`, `PASSWORD`, and `HOST` must be added. & For more details, see the reference documentation for \{\{link="https://docs.djangoproject.com/en/4.0/ref/settings/\#std:setting-DATABASES"\}\}DATABASES\{\{/link\}\}. \tn % Row Count 37 (+ 8) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Creating an app}} \tn % Row 0 \SetRowColor{LightBackground} `python manage.py startapp app\_name` & Create an app\_name directory and all default file/folder inside \tn % Row Count 4 (+ 4) % Row 1 \SetRowColor{white} `INSTALLED\_APPS = {[}\{\{nl\}\}~'app\_name',\{\{nl\}\}~...` & Apps are "plugable", that will "plug in" the app into the project \tn % Row Count 8 (+ 4) % Row 2 \SetRowColor{LightBackground} `urlpatterns = {[}\{\{nl\}\}~path('app\_name/', \seqsplit{include('app\_name.urls'))},\{\{nl\}\}~path('admin/', admin.site.urls), \{\{nl\}\}{]}` & Into urls.py from project folder, inculde app urls to project \tn % Row Count 15 (+ 7) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Creating models}} \tn % Row 0 \SetRowColor{LightBackground} `Class \seqsplit{ModelName(models.Model)`} & Create your class in the app\_name/models.py file \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} `title = \seqsplit{models.CharField(max\_length=100)`} & Create your \{\{link="https://docs.djangoproject.com/en/3.2/ref/models/fields/"\}\}fields\{\{/link\}\} \tn % Row Count 8 (+ 5) % Row 2 \SetRowColor{LightBackground} `def \_\_str\_\_(self):\{\{nl\}\}~return self.title` & It's important to add \_\_str\_\_() methods to your models, because objects' representations are used throughout Django's \seqsplit{automatically-generated} admin. \tn % Row Count 16 (+ 8) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Database editing}} \tn % Row 0 \SetRowColor{LightBackground} `python manage.py makemigrations (app\_name)` & By running makemigrations, you're telling Django that you've made some changes to your models \tn % Row Count 5 (+ 5) % Row 1 \SetRowColor{white} `python manage.py sqlmigrate \#identifier` & See what SQL that migration would run. \tn % Row Count 8 (+ 3) % Row 2 \SetRowColor{LightBackground} `python manage.py check` & This checks for any problems in your project without making migrations \tn % Row Count 12 (+ 4) % Row 3 \SetRowColor{white} `python manage.py migrate` & Create those model tables in your database \tn % Row Count 15 (+ 3) % Row 4 \SetRowColor{LightBackground} `python manage.py shell` & Hop into the interactive Python shell and play around with the free API Django gives you \tn % Row Count 20 (+ 5) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{7.9442 cm} x{9.3258 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Administration}} \tn % Row 0 \SetRowColor{LightBackground} `python manage.py createsuperuser` & Create a user who can login to the admin site \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} \seqsplit{`admin.site.register(ModelName)`} & Into app\_name/admin.py, add the model to administration site \tn % Row Count 6 (+ 3) % Row 2 \SetRowColor{LightBackground} \seqsplit{http://127.0.0.1:8000/admin/} & Open a web browser and go to "/admin/" on your local domain \tn % Row Count 9 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Management}} \tn % Row 0 \SetRowColor{LightBackground} `mkdir \seqsplit{app\_name/management} \seqsplit{app\_name/management/commands} \&\& cd \$\_` & Create required folders \tn % Row Count 4 (+ 4) % Row 1 \SetRowColor{white} `touch \seqsplit{your\_command\_name.py`} & Create a python file with your command name \tn % Row Count 7 (+ 3) % Row 2 \SetRowColor{LightBackground} `from \seqsplit{django.core.management.base} import BaseCommand\{\{nl\}\}\#import anything else you need to work with (models?)` & Edit your new python file, start with import \tn % Row Count 13 (+ 6) % Row 3 \SetRowColor{white} `class Command(BaseCommand):\{\{nl\}\}~~help = "This message will be shon with the -{}-help option after your command"\{\{nl\}\}\{\{nl\}\}~~def handle(self, {\emph{args, }}*kwargs):\{\{nl\}\}~~~\# Work the command is supposed to do` & Create the Command class that will handle your command \tn % Row Count 26 (+ 13) % Row 4 \SetRowColor{LightBackground} `python manage.py \seqsplit{my\_custom\_command`} & And this is how you execute your custom command \tn % Row Count 29 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{17.67cm}}{Django lets you create your customs CLI commands} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Write your first view}} \tn % Row 0 \SetRowColor{LightBackground} `from django.http import HttpResponse\{\{nl\}\}def index(request):\{\{nl\}\}~return HttpResponse("Hello, world. You're at the index.")` & Open the file app\_name/views.py and put the following Python code in it.\{\{nl\}\}This is the simplest view possible. \tn % Row Count 7 (+ 7) % Row 1 \SetRowColor{white} `from django.urls import path\{\{nl\}\}from . import views\{\{nl\}\}\{\{nl\}\}app\_name = "app\_name"\{\{nl\}\}urlpatterns = {[}\{\{nl\}\}~path('', views.index, name='index'),\{\{nl\}\} {]}` & In the app\_name/urls.py file include the following code. \tn % Row Count 16 (+ 9) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{View with argument}} \tn % Row 0 \SetRowColor{LightBackground} `def detail(request, question\_id):\{\{nl\}\}~return \seqsplit{HttpResponse(f"You're} looking at question \{question\_id\}")` & Exemple of view with an arugment \tn % Row Count 6 (+ 6) % Row 1 \SetRowColor{white} `urlpatterns = {[}\{\{nl\}\}~path('\textless{}int:question\_id\textgreater{}/', views.detail, name='detail'),\{\{nl\}\}~...` & See how we pass argument in path \tn % Row Count 11 (+ 5) % Row 2 \SetRowColor{LightBackground} `\{\% url \seqsplit{'app\_name:view\_name'} question\_id \%\}` & We can pass attribute from template this way \tn % Row Count 14 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{View with Template}} \tn % Row 0 \SetRowColor{LightBackground} \seqsplit{`app\_name/templates/app\_name/index}.html` & This is the folder path to follow for template \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} `context = \{'key': value\}` & Pass values from view to template \tn % Row Count 5 (+ 2) % Row 2 \SetRowColor{LightBackground} `return render(request, \seqsplit{'app\_name/index.html'}, context)` & Exemple of use of render shortcut \tn % Row Count 8 (+ 3) % Row 3 \SetRowColor{white} `\{\% Code \%\}\{\{nl\}\}\{\{ Variavle from view's context dict \}\}\{\{nl\}\}\textless{}a href="\{\% url 'detail' question.id \%\}"\textgreater{}\textless{}/a\textgreater{}` & Edit template with those. Full list \{\{link="https://docs.djangoproject.com/en/4.0/topics/templates/"\}\}here\{\{/link\}\} \tn % Row Count 14 (+ 6) % Row 4 \SetRowColor{LightBackground} `\textless{}title\textgreater{}Page Title\textless{}/title\textgreater{}` & you can put this on top of your html template to define page title \tn % Row Count 18 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Add some static files}} \tn % Row 0 \SetRowColor{LightBackground} \seqsplit{`'django.contrib.staticfiles'`} & Be sure to have this in your INSTALLED\_APPS \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} `STATIC\_URL = 'static/'` & The given exemples are for this config \tn % Row Count 5 (+ 2) % Row 2 \SetRowColor{LightBackground} `mkdir app\_name/static \seqsplit{app\_name/static/app\_name`} & Create static folder associated with your app \tn % Row Count 8 (+ 3) % Row 3 \SetRowColor{white} `\{\% load static \%\}` & Put this on top of your template \tn % Row Count 10 (+ 2) % Row 4 \SetRowColor{LightBackground} `\textless{}link rel="stylesheet" type="text/css" href="\{\% static \seqsplit{'app\_name/style.css'} \%\}"\textgreater{}` & Exemple of use of static. \tn % Row Count 15 (+ 5) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{10.362 cm} x{6.908 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Raising 404}} \tn % Row 0 \SetRowColor{LightBackground} `raise Http404("Question does not exist")` & in a try / except statement \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} `question = \seqsplit{get\_object\_or\_404(Question}, pk=question\_id)` & A shortcut \tn % Row Count 5 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Forms}} \tn % Row 0 \SetRowColor{LightBackground} `app\_name/forms.py` & Create your form classes here \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} `from django import forms` & Import django's forms module \tn % Row Count 4 (+ 2) % Row 2 \SetRowColor{LightBackground} `from .models import YourModel` & import models you need to work with \tn % Row Count 6 (+ 2) % Row 3 \SetRowColor{white} `class ExempleForm(forms.Form):\{\{nl\}\}~~exemple\_field = \seqsplit{forms.CharField(label='Exemple} label', max\_length=100)` & For very simple forms, we can use simple Form class \tn % Row Count 12 (+ 6) % Row 4 \SetRowColor{LightBackground} `class ExempleForm(forms.ModelForm):\{\{nl\}\}~class meta:\{\{nl\}\}~~model = model\_name\{\{nl\}\}~~fields = {[}"fields"{]}\{\{nl\}\}~~labels = \{"text": "label\_text"\}\{\{nl\}\}~~widget = \{"text": forms.widget\_name\}` & A ModelForm maps a model class's fields to HTML form \textless{}input\textgreater{} elements via a Form. Widget is optional. Use it to override default widget \tn % Row Count 24 (+ 12) % Row 5 \SetRowColor{white} `TextInput, EmailInput, PasswordInput, DateInput, Textarea` & Most common widget \{\{link="https://docs.djangoproject.com/en/3.2/ref/forms/widgets/"\}\}list\{\{/link\}\} \tn % Row Count 29 (+ 5) % Row 6 \SetRowColor{LightBackground} `if request.method != "POST":\{\{nl\}\}~~form = ExempleForm()` & Create a blank form if no data submitted \tn % Row Count 33 (+ 4) \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Forms (cont)}} \tn % Row 7 \SetRowColor{LightBackground} `form = \seqsplit{ExempleForm(data=request}.POST)` & The form object contain's the informations submitted by the user \tn % Row Count 4 (+ 4) % Row 8 \SetRowColor{white} `is form.isvalid()\{\{nl\}\}~~form.save()\{\{nl\}\}~~return \seqsplit{redirect("app\_name:view\_name"}, argument=ardument)` & Form validation. Always use redirect function \tn % Row Count 11 (+ 7) % Row 9 \SetRowColor{LightBackground} `\{\% csrf\_token \%\}` & Template tag to prevent "cross-site request forgery" attack \tn % Row Count 14 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Render Form In Template}} \tn % Row 0 \SetRowColor{LightBackground} `\{\{ form.as\_p \}\}` & The most simple way to render the form, but usualy it's ugly \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} `\{\{ \seqsplit{field|placeholder:field}.label \}\} \{\{nl\}\} \{\{ \seqsplit{form.username|placeholder:"Your} name here"\}\}` & The | is a filter, and here for placeholder, it's a custom one. See next section to see how to create it \tn % Row Count 9 (+ 6) % Row 2 \SetRowColor{LightBackground} `\{\% for field in form \%\} \{\{nl\}\} \{\{form.username\}\}` & You can extract each fields with a for loop. \{\{nl\}\} Or by explicitly specifying the field \tn % Row Count 14 (+ 5) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Custom template tags and filters}} \tn % Row 0 \SetRowColor{LightBackground} `app\_name\textbackslash{}templatetags\textbackslash{}\_\_init\_\_.py` & Create this folder and this file. Leave it blank \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} `app\_name\textbackslash{}templatetags\textbackslash{}filter\_name.py` & Create a python file with the name of the filter \tn % Row Count 6 (+ 3) % Row 2 \SetRowColor{LightBackground} `\{\% load filter\_name \%\}` & Add this on top of your template \tn % Row Count 8 (+ 2) % Row 3 \SetRowColor{white} `from django import template \{\{nl\}\}\{\{nl\}\} register = template.Library()` & To be a valid tag library, the module must contain a module-level variable named register \{\{nl\}\} that is a template.Library instance \tn % Row Count 15 (+ 7) % Row 4 \SetRowColor{LightBackground} \seqsplit{`@register.filter(name='cut')} \{\{nl\}\} def cut(value, arg): \{\{nl\}\}~~ """Removes all values of arg from the given string""" \{\{nl\}\}~~ return value.replace(arg, '')` & Here is an exemple of filter definition. \{\{nl\}\} See the decorator? It registers your filter with your Library instance. \{\{nl\}\} You need to restart server for this to take effects \tn % Row Count 25 (+ 10) % Row 5 \SetRowColor{white} \seqsplit{https://tech.serhatteker.com/post/2021-06/placeholder-templatetags/} & Here is a link of how to make a placeholder custom template tag \tn % Row Count 29 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Setting Up User Accounts}} \tn % Row 0 \SetRowColor{LightBackground} Create a "users" app & Don't forget to add app to settings.py and include the URLs from users. \tn % Row Count 4 (+ 4) % Row 1 \SetRowColor{white} `app\_name = "users"\{\{nl\}\}urlpatterns{[}\{\{nl\}\}~~\# include default auth urls.\{\{nl\}\}~~path("", \seqsplit{include("django.contribe.auth}.urls"))\{\{nl\}\}{]}` & Inside app\_name/urls.py (create it if inexistent),\{\{nl\}\}this code includes some default authentification URLs that Django has defined. \tn % Row Count 12 (+ 8) % Row 2 \SetRowColor{LightBackground} `\{\% if form.error \%\}\{\{nl\}\}~~\textless{}p\textgreater{}Your username and password didn't match\textless{}/p\textgreater{}\{\{nl\}\}\{\% endif \%\}\{\{nl\}\}\textless{}form method="post" action="\{\% url 'users:login' \%\}"\textgreater{}\{\{nl\}\}~~\{\% csrf\_token \%\}\{\{nl\}\}~~\{\{ form.as\_p \}\}\{\{nl\}\}\{\{nl\}\}~~\textless{}button name="submit"\textgreater{}Log in\textless{}/button\textgreater{}\{\{nl\}\}~~\textless{}input type="hidden" name="next" value=" \{\% url 'app\_name:index' \%\}" /\textgreater{}\{\{nl\}\}\textless{}/form\textgreater{}` & Basic login.html template\{\{nl\}\}Save it at save template as \seqsplit{users/templates/registration/login}.html\{\{nl\}\}We can access to it by using\{\{nl\}\}`\textless{}a href="\{\% url 'users:login' \%\}"\textgreater{}Log in\textless{}/a\textgreater{}` \tn % Row Count 32 (+ 20) \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Setting Up User Accounts (cont)}} \tn % Row 3 \SetRowColor{LightBackground} `\{\% if \seqsplit{user.is\_authenticated} \%\}` & Check if user is logged in \tn % Row Count 2 (+ 2) % Row 4 \SetRowColor{white} `\{\% url "users:logout" \%\}` & Link to logout page, and log out the user\{\{nl\}\}save template as \seqsplit{users/templates/registration/logged\_out}.html \tn % Row Count 8 (+ 6) % Row 5 \SetRowColor{LightBackground} `path("register/", views.register, name="register"),` & Inside app\_name/urls.py, add path to register \tn % Row Count 11 (+ 3) % Row 6 \SetRowColor{white} `from django.shortcuts import render, redirect\{\{nl\}\}from django.contrib.auth import login\{\{nl\}\}from \seqsplit{django.contrib.forms} import UserCreationForm\{\{nl\}\}\{\{nl\}\}def register(request):\{\{nl\}\}~~if request.method != "POST":\{\{nl\}\}~~~~form = UserCreationForm()\{\{nl\}\}~~else:\{\{nl\}\}~~~~form = \seqsplit{UserCreationForm(data=request}.POST)\{\{nl\}\}\{\{nl\}\}~~~~if form.is\_valid():\{\{nl\}\}~~~~~~new\_user = form.save()\{\{nl\}\}~~~~~~login(request, new\_user)\{\{nl\}\}~~~~~~return redirect("app\_name:index")\{\{nl\}\}\{\{nl\}\}~~context = \{"form": form\}\{\{nl\}\}~~return render(request, \seqsplit{"registration/register}.html", context)` & We write our own register() view inside users/views.py\{\{nl\}\}For that we use UserCreationForm, a django building model.\{\{nl\}\}If method is not post, we render a blank form\{\{nl\}\}Else, is the form pass the validity check, an user is created\{\{nl\}\}We just have to create a registration.html template in same folder as the login and logged\_out \tn % Row Count 50 (+ 39) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Allow Users to Own Their Data}} \tn % Row 0 \SetRowColor{LightBackground} `...\{\{nl\}\}from \seqsplit{django.contrib.auth.decorators} import login\_required\{\{nl\}\}...\{\{nl\}\}\{\{nl\}\}@login\_required\{\{nl\}\}def my\_view(request)\{\{nl\}\}~~...` & Restrict access with @login\_required decorator\{\{nl\}\}\{\{nl\}\}If user is not logged in, they will be redirect to the login page\{\{nl\}\}To make this work, you need to modify settings.py so Django knows where to find the login page\{\{nl\}\}Add the following at the very end\{\{nl\}\}`\# My settings\{\{nl\}\}LOGIN\_URL = "users:login"` \tn % Row Count 16 (+ 16) % Row 1 \SetRowColor{white} `...\{\{nl\}\}from \seqsplit{django.contrib.auth.models} import User\{\{nl\}\}...\{\{nl\}\}owner = \seqsplit{models.ForeignKey(User}, \seqsplit{on\_delete=models.CASCADE)`} & Add this field to your models to connect data to certain users\{\{nl\}\}\{\{nl\}\}When migrating, you will be prompt to select a default value \tn % Row Count 23 (+ 7) % Row 2 \SetRowColor{LightBackground} `user\_data = \seqsplit{ExempleModel.objects.filter(owner=request.user)`} & Use this kind of code in your views to filter data of a specific user\{\{nl\}\}request.user only exist when user is logged in \tn % Row Count 30 (+ 7) \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Allow Users to Own Their Data (cont)}} \tn % Row 3 \SetRowColor{LightBackground} `...\{\{nl\}\}from django.http import Http404\{\{nl\}\}...\{\{nl\}\}\{\{nl\}\}...\{\{nl\}\}if exemple\_data.owner != request.user:\{\{nl\}\}~~raise Http404` & Make sure the data belongs to the current user\{\{nl\}\}\{\{nl\}\}If not the case, we raise a 404 \tn % Row Count 8 (+ 8) % Row 4 \SetRowColor{white} `new\_data = form.save(commit=false)\{\{nl\}\}new\_data.owner = request.user\{\{nl\}\}new\_data.save()` & Don't forget to associate user to your data in corresponding views\{\{nl\}\}\{\{nl\}\}The "commit=false" attribute let us do that \tn % Row Count 15 (+ 7) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Paginator}} \tn % Row 0 \SetRowColor{LightBackground} `from \seqsplit{django.core.paginator} import Paginator` & In app\_name/views.py, import Paginator \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} `exemple\_list = \seqsplit{Exemple.objects.all()`} & In your class view, Get a list of data \tn % Row Count 5 (+ 2) % Row 2 \SetRowColor{LightBackground} `paginator = \seqsplit{Paginator(exemple\_list}, 5) \# Show 5 items per page.` & Set appropriate pagination \tn % Row Count 9 (+ 4) % Row 3 \SetRowColor{white} `page\_number = \seqsplit{request.GET.get('page')`} & Get actual page number \tn % Row Count 11 (+ 2) % Row 4 \SetRowColor{LightBackground} `page\_obj = \seqsplit{paginator.get\_page(page\_number)`} & Create your Page Object, and put it in the context \tn % Row Count 14 (+ 3) % Row 5 \SetRowColor{white} `\{\% for item in page\_obj \%\}` & The Page Object acts now like your list of data \tn % Row Count 17 (+ 3) % Row 6 \SetRowColor{LightBackground} `\textless{}div class="pagination"\textgreater{}\{\{nl\}\}~~\textless{}span class="step-links"\textgreater{}\{\{nl\}\}~~\{\% if \seqsplit{page\_obj.has\_previous} \%\}\{\{nl\}\}~~~~\textless{}a href="?page=1"\textgreater{}\« first\textless{}/a\textgreater{}\{\{nl\}\}~~~~\textless{}a href="?page=\{\{ \seqsplit{page\_obj.previous\_page\_number} \}\}"\textgreater{}previous\textless{}/a\textgreater{}\{\{nl\}\}~~\{\% endif \%\}\{\{nl\}\}~~~~\textless{}span class="current"\textgreater{} Page \{\{ page\_obj.number \}\} of \{\{ \seqsplit{page\_obj.paginator.num\_pages} \}\}. \textless{}/span\textgreater{}\{\{nl\}\}~~\{\% if page\_obj.has\_next \%\} \{\{nl\}\}~~ \textless{}a href="?page=\{\{ \seqsplit{page\_obj.next\_page\_number} \}\}"\textgreater{}next\textless{}/a\textgreater{} \{\{nl\}\}~~ \textless{}a href="?page=\{\{ \seqsplit{page\_obj.paginator.num\_pages} \}\}"\textgreater{}last \»\textless{}/a\textgreater{} \{\{nl\}\}~~ \{\% endif \%\} \{\{nl\}\}~~ \textless{}/span\textgreater{} \{\{nl\}\} \textless{}/div\textgreater{}` & An exemple of what to put on the bottom of your page \{\{nl\}\} to navigate through Page Objects \tn % Row Count 53 (+ 36) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Deploy to Heroku}} \tn % Row 0 \SetRowColor{LightBackground} https://heroku.com & Make a Heroku account \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} \seqsplit{https://devcenter.heroku.com:articles/heroku-cli/} & Install Heroku CLI \tn % Row Count 5 (+ 3) % Row 2 \SetRowColor{LightBackground} `pip install psycog2`\{\{nl\}\}`pip install django-heroku`\{\{nl\}\}`pip install gunicorn` & install these packages \tn % Row Count 10 (+ 5) % Row 3 \SetRowColor{white} `pip freeze \textgreater{} requirements.txt` & updtate requirements.txt \tn % Row Count 12 (+ 2) % Row 4 \SetRowColor{LightBackground} `\# Heroku settings.`\{\{nl\}\}`import django\_heroku`\{\{nl\}\}`django\_heroku.settings(locals(), staticfiles=False)`\{\{nl\}\}`if \seqsplit{os.environ.get('DEBUG')} == "TRUE":`\{\{nl\}\}~~`DEBUG = True`\{\{nl\}\}~~`elif \seqsplit{os.environ.get('DEBUG')} == "FALSE":`\{\{nl\}\}~~`DEBUG = False` & At the very end of settings.py, make an Heroku ettings section\{\{nl\}\}import django\_heroku and tell django to apply django heroku settings\{\{nl\}\}The staticfiles to false is not a viable option in production, check whitenoise for that IMO \tn % Row Count 26 (+ 14) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \end{document}