Modles
Example data model
class Customer(models.Model):
MEMBERSHIP_BRONZE = 'B'
MEMBERSHIP_SILVER = 'S'
MEMBERSHIP_GOLD = 'G'
MEMBERSHIP_CHOICES = [
(MEMBERSHIP_BRONZE, 'Bronze'),
(MEMBERSHIP_SILVER, 'Silver'),
(MEMBERSHIP_GOLD, 'Gold'),
]
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField(unique=True)
phone = models.CharField(max_length=255)
birth_date = models.DateField(null=True)
membership = models.CharField(
max_length=1, choices=MEMBERSHIP_CHOICES, default=MEMBERSHIP_BRONZE)
def __str__(self):
return self.first_name
Django ORM
Example queryset
queryset = Product.objects.filter(inventory__lt=10)
And (chaining)
# Use chaining for simple and queries
# Products where inventory < 10 and unit_price < 20
queryset = Product.objects.filter(inventory__lt=10).filter(unit_price__lt=20)
Q-objects (Or, And, Not)
# Products where inventory < 10 OR unit_price < 10 '
queryset = Product.objects.filter(Q(inventory__lt=10) | Q(unit_price__lt=20))
# Products where inventory < 10 AND NOT unit_price < 10
.filter(Q(inventory__lt=10) &~ Q(unit_price__lt=20))
F-Objects
# F-ield-objects are for when you want to compare columns
# Products where inventory = unit_price
queryset = Product.objects.filter(inventory=F('unit_price'))
Sorting
# All products sorted by title - ASC order
queryset = Product.objects.order_by('title')
# All products sorted by title - DESC order
.order_by('-title')
# Mutiple arguments
# Most expencive products in title ASC order
.order_by('-unit_price', 'title')
# Reverse last example
.order_by('-unit_price', 'title').reverse()
# Indexing - Returns object right away
.order_by('unit_price')[0]
# Indexing - Returns queryset
.earliest('unit_price')
.latest('unit_price')
# Slicing
.order_by('unit_price')[:5]
Selecting specific fields
# Returns dictionary, does'nt return an object.
queryset = Product.objects.values('id', 'title', 'collection')
# Returns touple.
.values_list('id', 'title', 'collection')
# Returns instance with only attributes 'id' and 'title'.
# Careful! You can accidentally overload the db with queryies, if you handle wrong!
# Say if you later want 'description' later in a for-loop, then django will need to send a query for all objects.
.only('id', 'title')
# Same but opposite to only, returns instance with all attributes except 'id' and 'title'
.defer('id', 'title')
Pre-loading other tables
# This pre-loads (join the tables) the collection-table so you don't need to ask the db for each product later on.
# One-to-one joins, one product has one collection
queryset = Product.objects.select_related('collection').all()
# One-to-many join
.prefetch_related('promotions')
Aggregate
Examples
orders_placed = Order.objects.aggregate(Count=Count('id'))
units_sold = OrderItem.objects \
.filter(product_id=1) \
.aggregate(units_sold=Sum('quantity'))
orders_placed = Order.objects\
.filter(customer_id=1)\
.aggregate(orders_placed=Count('id'))
min_max_avg_collection_3 = Product.objects\
.filter(collection_id=3)\
.aggregate(
max=Max('unit_price'),
min=Min('unit_price'),
avg=Avg('unit_price'))
Annotate
# When you wanna ADD attributes to our object when querying them
# Adds a new column 'new_id' and sets it to the original id :)
queryset = Customer.objects.annotate(new_id=F('id'))
Call db-function
# Concatenation, obs do next example instead
queryset = Customer.objects.annotate(
custom_name_of_field=Func(F('first_name'), Value(' '), F('last_name'), function='CONCAT')
)
# Same but with a Concat object
queryset = Customer.objects.annotate(
full_name=Concat('first_name', Value(' '), 'last_name')
)
# Number of orders for each customer
.annotate(orders_count=Count('order'))
# Collections and count of their products
.annotate(products = Count('product'))
# Customers with more than 5 orders
.annotate(orders_count=Count('order')).filter(orders_count__gt=5)
#
The Admin Site
Register models
Django Admin Site Doc
# Example model to display in admin
@admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ['title', 'unit_price', 'inventory_status']
list_editable = ['unit_price']
list_per_page = 10
@admin.display(ordering='inventory')
def inventory_status(self, product):
if product.inventory < 10:
return 'Low'
return 'OK'