Django Notes: To Create A New Project

Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

Django Notes

To create a new project


django-admin startproject project-name path/to/project/dir

To start the django server to serve a project


python manager.py runserver

To create a new app


django-admin startapp app-name
You will need to add the app-name to the settings.py → INSTALLED_APPS

In an app:
apps.py is for configurations
models.py is for models
views.py is for actions (request handlers)
urls.py we should define an array called urlpatterns. It’s an array of the form:
urlpatterns = [
path(‘url/path/’, action_function_ref),
path(‘url/path2/’, include(‘playgounds.urls’),
]

- To create a model you should create a new class in the app’s model.py. This new class must inherit
from django.db.models.Model. Example of a model class is:
- django creates an id field by default for each model. To prevent that create any other field and mark it
as primery_key=True.
- You need to declare the relations only in one side not on both sides and djando will declare the other
automatically. To prevent that you can mark the field with related_name=’+’.

from django.db import models

class Collection(models.Model):

title = models.CharField(max_length=255)

class Promotion(models.Model):

title = models.CharField(max_length=255)

discount = models.FloatField()

class Product(models.Model):

title = models.CharField(max_length=255)

description = models.TextField()

price = models.DecimalField(max_digits=10, decimal_places=2)

created_at = models.DateTimeField(auto_now_add=True) # This will be set once (with


now()) when the record in added

updated_at = models.DateTimeField(auto_now=True) # This will be updated always with


now()

collection = models.ForeignKey(Collection, on_delete=models.PROTECT)

promotions = models.ManyToManyField(Promotion, related_name='products') # related_name


will be used in the reverse part on the relationship (in Promotion class)

class Customer(models.Model):

MEMBERSHIPS_LIST = [

('B', 'Bronze'),

('S', 'Silver'),

('G', 'Gold')

name = models.CharField(max_length=255)

email = models.EmailField(unique=True)

birth_date = models.DateField(null=True)
membership = models.CharField(max_length=1, choices=MEMBERSHIPS_LIST, default='B')

class Address(models.Model):

street = models.CharField(max_length=255)

customer = models.OneToOneField(Customer, on_delete=models.CASCADE, primary_key=True)


# primary_key=True is mandatory for 1-to-1 relationship

- You can have some customization over the created DB for each model by creating Meta class inside
the class of the model
Example:
class Customer(models.Model):
MEMBERSHIPS_LIST = [
('B', 'Bronze'),
('S', 'Silver'),
('G', 'Gold')
]
name = models.CharField(max_length=255)
email = models.EmailField(unique=True)
birth_date = models.DateField(null=True)
membership = models.CharField(max_length=1, choices=MEMBERSHIPS_LIST, default='B')
class Meta:
indexes = [
models.Index(fields=['name']),
models.Index(fields=['membership']),
]

Migrations:
- To create a migration:
python manage.py makemigrations
- To run migrations:
pyhton manage.py migrate
- To go to a specified migrations:
pyhton manage.py migrate customer 003

Change DB settings:
- Go to settings.py and change the DATABASE settings

for generating mock DB data


http://mockaroo.com
Django ORM:
Product.objects this is called the manager of the Product model.
query_set = Product.objects.all() this doesn’t execute any SQL query yet, instead it prepare the query
and returns a query set, then when you iterate over the query set or convert it to a list (using
list(query_set)), or slice it (e.g using query_set[0:5]) the SQL query will be executed and the data will
be retrieved from the DB. This is called a lazy object.
For filtering:
• Product.objects.filter(id=10)

• Product.objects.filter(collection__id=1) # foreign key vlaue

• Product.objects.filter( price__lt=100.0) # price < 100.0

• Product.objects.filter( price__range=(10,100.0)) # 10.0 < price < 100.0

• Product.objects.filter(collection__id__range=(1,2,3))# get all products with


collection ids in {1, 2, 3}

• Product.objects.filter( price__range=(10,100.0)) # 10.0 < price < 100.0

• Product.objects.filter( title__icontains=”bla”) # title ILIKE “%bla%”

• Product.objects.filter(description__isnull=True)

• To make AND operation make stacked filers,


Product.objects.filter(collection__id=1).filter(title__contains=”abc”)

• Another method to make AND/OR operation is to use Q object: Product.objects.filter(


Q(collection__id=1) & Q(title__contains=”abc”)).

• For Q objects we use bit-wise operator like &, |, and ~ .

• To reference a field inside a filter use F. Example:


Product.objects.filter(title=F(‘description’)). This means title = description.

For sorting:
• Product.objects.filter( price__lt=100.0).order_by(“title”, “-desciption”). This sort
by title ascending and description descending.

For limiting the query to a number of fields:


• Product.objects.values(‘id’, ‘title’) this is to retrieve only the id and title

• Product.objects.values(‘id’, ‘title’, ‘collection_title’) this will make inner join


with the collection table to retrieve collection’s titles as well.

For querying related tables:


When we call e.g Product.objects.all() it fetches the data of only the Product table not the related
table.
In order to fetch related tables we either need to call select_related method if the table that need to be
fetched has one instance for an instance of the current table (the Product table), or call
prefetch_related if the table that need to be fetched has many instances for an instance of the current
table (the Product table). Examples:
Product.objects.select_related(‘collection’).all()

This will fetch also the collection table. Note that ‘collection’ is the name of a field in the Product
model.
Product.objects.prefetch_related(‘promotions’).all()

Aggregate functions:
result = Product.objects.aggregate(prod_count=Count(‘id’))
Note this will return a dictionary in the form:
{‘prod_count’: 1000}

Adding calculated/on-the-fly fields to objects:


We can do this using annotate method, example:
query_set = Customer.objects.annotate(is_new=Value(True))
the value of any new field must be an expression; To create an expression you can use one of the
following functions:
• F: for table’s fields.
• Value: for literal values.
• Func: for calling DB functions.
Example of creating a calculated filed by called the stored function ‘CONCAT’:
query_set = Customer.objects.annotate(full_name=Func(F(‘first_name’), Value(‘ ‘),
F(‘last_name’), function=’CONCAT’))
Note: there is another method of calling stored procedures described here.

ExpressionWrapper:
Used for casting the results of an expression into a new type.

Custom Manager:
class ProductManager(models.Manager):
def fn_that_do_complex_process(self, params):
pass
Then in the Product model class you need to add the following attribute:
class Product(models.Model):
objects = ProductManager()
……

Then we can call it using:


Product.objects. fn_that_do_complex_process(params)

Query set cash:


The Query set has a cash that cash the results of a query so that it will not call the SQL query again for
the same or subset of the cashed query. Example:
query_set = Product.objects.all()
products = list(query_set)

first_product = query_set[0]

The last line will not generate a new SQL query, but will use the cashed data.

Creating Objects:
method 1:
product = Product()

product.title = ‘good product’

product.description = ‘Bla bla bla’

product.collection = Collection(id=2)

product.save()

print(prodcut.id) # the is is ready here

method 2:
product = Product.objects.create(title=‘good product’, description=‘Bla bla bla’,
collection_id=2)

Updating Objects:
method 1:
customer = Customer.objects.get(pk=1)

customer.last_name = 'Soso'

customer.save()

method 2:
Customer.objects.filter(id=1).update(last_name='Soso')

Note that method 2 is better performance wise because you don’t have to read the object first from the
DB then update it.

Deleting Objects:
method 1:
customer = Customer(pk=1)

customer.delete()

method 2:
Customer.objects.filter(id__gt=5).delete()

Transactions:
To run a multiple statements inside a DB transaction you can either annotate their method with:
@transaction.atomic()
Or wrap the code in a with block:
with transaction.atomic():
bla bla bla

Writing raw SQL queries:


If the raw SQL query is related to one model (table), you can use the following approach:
query_set = Product.objects.raw(‘SELECT * FROM store_product’)
This will return a query set that will have key-values for the fields.
Note that the returned query_set doesn’t have filter or annotate method unlike the normal query sets.

Otherwise if our raw SQL query will not be mapped to only one model we can use the following
approach:
try:
cursor = connection.cursor()
cursor.execute(‘SOME COMPLEX QUERY’)

catch Exception:
pass
finally:
cursor.close()
Or instead of using try catch you can use with clause:
with connection.cursor() as cursor:
cursor.execute(‘SOME COMPLEX QUERY’)

You can also use this last method to call DB stored procedures:
with connection.cursor() as cursor:
cursor.callproc(‘my_sp’, [‘str_param1’, int_praram2])

Admin site
Note: the admin site depends on the Session App, so you need to add it to the installed app first
('django.contrib.sessions'), then run migrate.
To create new admin user:
python manage.py createsuperuser

python manage.py changepassword admin

Then you need to register the models you want to display in the admin page by adding the following
line to the app’s admin.py file:
admin.site.register(models.Collection)

To show a message to the user:


From inside any model:
self.message_user(request, ‘message to show’, message.INFO)

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy