steps taken from: https://tutorial.djangogirls.org/en/django_start_project/
start venv
/home/user/dev/myblog
virtualvenv venv
. venv/bin/activate
install django
pip install django
start new project
django-admin startproject myBlog
review myBlog/settings.py, DB settings etc
create database
python manage.py migrate
start webserver
python manage.py runserver
check the URL generated to see if its running
create new application under your project -- example, myBlog/blog
python manage.py startapp blog
a new 'blog' dir is created under project path
edit 'settings.py' and add your applicatoin to INSTALLED_APPS parameter
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog']edit models.py, add this (replace out of box contents)
from django.db import modelsfrom django.utils import timezonecreate a DB Migrations file, this will add Blog model to DB
python manage.py makemigrations blog
create the model
python manage.py migrate blog
Create an Admin login page
open blog/admin.py replace contents with this,
from django.contrib import admincreate an Admin user
python manage.py createsuperuser
Insert / Create
models.pycreate a new Employee row
## views.pyfrom .models import Employeee = Employee(account_id=234, fname="joe", lname="smith")e.save()update existing Employee row (search for specific row, then update it)
e = Employee.objects.get(fname="joe")e.fname = "fred"e.save()Queries
get # of records
Cars.objects.all().count()distinct / unique count
Cars.objects.distinct().count()get distinct values
Cars.objects.values("Chevy").distinct().count()get datetime YYYY of creation
Cars.objects.dates("created", "year")Order by
Cars.objects.all().order_by("color")order by color ascending, brand descending
Cars.objects.all().order_by("color", "-brand")get first 5 records
Cars,objects.filter(color="red")[:5]latest / earliest
Cars.objects.latest("created") # or earliestRAW SQL
pass parameter to raw sql
drinks_low_caffeine = Drink.objects.raw("SELECT * FROM items_drink where caffeine < %s",params=[caffeine_limit]);Prefetch Objects: The prefetch_related() function reduces and optimizes the number of database hits.
from django.db.models import Prefetchfrom .models import Author, BookIn the above example, for each author in authors, the related books are prefetched from the database, but only if their title contains 'Django'. This can significantly optimize database queries when dealing with related objects.
F() Expressions: F() expressions allow you to refer to model field values and perform database operations using them. They can be particularly useful for making atomic updates.
from django.db.models import Ffrom .models import ProductIn this example, the F() expression is used to decrement the stock of all products by one directly in the database, which is more efficient and safe against race conditions.
Many To Many
create M2M relations (sandwich to sauces)
get reverse relations using Set
bbq_sauce.sandwich_set.all()<QuerySet [<Sandwich: Chicken Teriyaki>]>filter specific subset
Sandwich.objects.filter(sauces__name="Barbeque sauce")display Server Name in template:
{% for row in qs_dict %}{{ row.server_name }}Queries
get specific row by PK
e = Employee.objects.get(pk=123)get all rows
e = Employee.objects.all()search by specific field (WHERE)
e = Employee.objects.filter(fname="joe")AND query
# Get the Store records that have state 'CA' AND city 'San Diego'Store.objects.filter(state='CA', city='San Diego')complex AND
queryset = User.objects.filter( Q(first_name__startswith='R') & Q(last_name__startswith='D')OR query
from django.db.models import QStore.objects.filter(Q(state='CA') | Q(state='AZ')AND NOT (starts with R and NOT starts with Z
queryset = User.objects.filter( Q(first_name__startswith='R') & ~Q(last_name__startswith='Z')less than or equal to
e = Employee.objects.filter(age__lte=20)search by case insensitive
e = Employee.objects.get(fname__iexact="joe")search any row that contains string
e = Employee.objects.get(fname__contains="jo")search across multiple tables (JOIN)
e = Employee.objects.filter(roles__name="worker")JOIN with Contains
e = Employee.objects.filter(roles__name__contains="work")EXCLUDE query
# Get the Store records that don't have state 'CA'Store.objects.exclude(state='CA')NULL query
# Get the Store records that have email NULLStore.objects.filter(email__isnull=True)Find value from IN list
# Get the Store records that have state 'CA' OR state='AZ'Store.objects.filter(state__in=['CA','AZ'])CONTAINS, STARTSWITH, ENDSWITH
Get the Store records that contain a 'C' anywhere in state (LIKE '%C%')
Store.objects.filter(state__contains='C')Get the Store records that start with 'San' in city (LIKE 'San%')
Store.objects.filter(city__startswith='San')Get the Item records that end with 'e' in name (LIKE '%e')
Drink.objects.filter(item__name__endswith='e')select only certtain fields
qs = Article.objects.only("author")select all fields EXCEPT these 2
qs = Article.objects.defer("create_date", "rating")get # of hits from a query
num_of_articles = Article.objects.all().count()check if query set contains an object
Article.objects.contains(article)get average
# Average price across all books, provide default to be returned instead of None if no books exist.
from django.db.models import AvgBook.objects.aggregate(Avg("price", default=0)){'price__avg': 34.35}get total count
# Total number of books with publisher=BaloneyPress
Book.objects.filter(publisher__name="BaloneyPress").count()73get Max number
# Max price across all books, provide default to be returned instead of None if no books exist.
from django.db.models import MaxBook.objects.aggregate(Max("price", default=0)){'price__max': Decimal('81.20')}Create dynamic queryset values with Annotate
ie, create dynamic value service_ok and service_error for any Host that has Services with state=1 (error)
(Service model has FK to Host, Many services > to 1 Host)
in Template can pass the svc dynamic values:
{% for host in allhosts %}for frequently accessed queryset data, use a cache, this will store all Articles in a cache for 3600 seconds (1 hour)
from django.core.cache import cachefrom .models import Article
Django Channels is a fantastic tool that extends Django to handle WebSockets, long-poll HTTP, and other asynchronous protocols. While it’s typically associated with real-time communication features, like chat apps, Channels can also be leveraged to manage asynchronous tasks in your Django application. Let’s take a look at how you can exploit this powerful feature.
Running Asynchronous Tasks: Django Channels uses an event-driven architecture powered by ASGI (Asynchronous Server Gateway Interface). This makes it a great tool for managing tasks that could benefit from asynchronous execution. For example, if you have a resource-intensive task that you don’t want to block your server’s response, you can offload that task to Django Channels.
from channels.layers import get_channel_layerfrom asgiref.sync import async_to_syncIn the consumer:
class ExpensiveConsumer(AsyncConsumer): async def expensive_task(self, event): # Your expensive task here passThis will allow your view to quickly respond to the user while the expensive task is processed in the background.
custom Template tags
To create a custom template tag, you first need to create a Python module in a Django app and define your custom function there.
# myapp/templatetags/my_custom_tags.pyIn your template, you would load the custom tags and then use them:
{% load my_custom_tags %}<p>{{ my_string|lower }}</p>Template Context Processors
A context processor is a Python function that takes the request object as an argument and returns a dictionary to add to the context. They’re specified using the TEMPLATE_CONTEXT_PROCESSORS setting and are a fantastic way to make sure certain data is available to all your templates.
Let’s create a context processor that adds the current year to every template:
# myapp/context_processors.pyMake sure you’ve added the context processor to your settings.py:
TEMPLATES = [ { # ... 'OPTIONS': { 'context_processors': [ # ... 'myapp.context_processors.current_year', ], }, },]Now, you can access the current year in your templates:
<footer> © {{ current_year }} My Amazing Site</footer>Clickjacking Protection: Clickjacking is a malicious technique where an attacker tricks a user into clicking something different from what the user perceives, potentially leading to unwanted actions. Django provides a middleware to protect against clickjacking by setting the X-Frame-Options header in HTTP responses. To activate this protection, add 'django.middleware.clickjacking.XFrameOptionsMiddleware' to your MIDDLEWARE settings:
By default, the header is set to DENY, meaning the page cannot be displayed in a frame. You can adjust this using the X_FRAME_OPTIONS setting.
Host Header Validation: Django uses the host header in the incoming HTTP request to construct URLs in certain cases. However, a maliciously crafted host header could lead to vulnerabilities. From version 1.10.3 onwards, Django validates the host header against the ALLOWED_HOSTS setting and returns a 400 Bad Request response if the host header doesn’t match any pattern in the list.
ALLOWED_HOSTS = ['mywebsite.com', 'www.mywebsite.com']It’s important to keep this setting up-to-date as your project grows or changes environments.
SECURE_PROXY_SSL_HEADER Setting: If your Django app is behind a proxy that’s serving HTTPS, Django needs to know when a request is secure so it can generate appropriate URLs and avoid redirect loops. In this scenario, you can use the SECURE_PROXY_SSL_HEADER setting. This is a tuple representing a header/value pair that a proxy sets when handling HTTPS requests:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')Be cautious with this setting; only use it when you control both the Django app and the proxy, as it can lead to security issues if misconfigured.
show request data
for key, val in request.POST.items():get specific value from Request
myval = request.GET.get("myval", "")Static Files
check if Django sees file in Static DIRS
./manage.py findstatic /assets/compiled/css/app.cssabstract models (reuse base model for multiple models)
class BaseProfile(models.Model): bio = models.TextField() avatar = models.ImageField(upload_to='avatars/') class Meta: abstract = Truemultiple indexes on a table
class User(models.Model): username = models.CharField(max_length=100, db_index=True) email = models.CharField(max_length=100)
pass a value from Form to a backend route
<input type="hidden" name="username" value="Bob">in route:
username = request.POST.get("username")