Django templates - lorem ipsum


Django tip:

You can generate lorem ipsum inside a Django template with the lorem tag.

https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#lorem

You can provide any (or none) of the following arguments:

  1. count - number of paragraphs or words
  2. method - words/HTML paragraphs/plain-text paragraphs
  3. random - doesn't use the common paragraph ("Lorem ipsum dolor sit amet...")

Example:

{% lorem 6 p random &}

# generates 6 paragraphs of text that doesn't
# start with "Lorem ips um dolor sit amet"

Django - update_or_create


Django's update_or_create() method either-

  • updates an existing object with the given kwargs along with a defaults dictionary of pairs for updating the object
  • creates a new object if it doesn't exist

It returns a tuple containing an object and a boolean specifying whether a new object was created.

Visitor.objects.create(name="Harry", surname="Potter", age=16)

visitor, created = Visitor.objects.update_or_create(
    name="Harry", surname="Potter", defaults={"age": 21}
)

print(visitor.age)
# => '21'

print(created)
# => False

Django - get_or_create


Django's get_or_create() method either-

  • gets an existing object with the given kwargs
  • creates a new object if it doesn't exist

It returns a tuple containing an object and a boolean specifying whether a new object was created.

Visitor.objects.create(name="Harry", surname="Potter", age=16)

visitor, created = Visitor.objects.get_or_create(
    name="Harry", surname="Potter", age=16
)
print(created)
# => False

visitor, created = Visitor.objects.get_or_create(
    name="Hermione", surname="Granger", age=16
)
print(created)
# => True

Django QuerySet - only() vs defer() vs exclude()


If you have some fields in your Django model that contain a lot of data and you don't need those fields for a particular query, you can tell Django not to retrieve them with defer():

Event.objects.defer("description")

While defer() works at the attribute level, exclude() works on the row level.

In other words, exclude() arguments are used after the WHERE clause -- i.e., SELECT * FROM users WHERE name = 'jan' -- while defer() changes * to the provided fields -- i.e., SELECT name, email FROM users.

Opposite to defer() is only(). If you have fewer fields that you want to retrieve than those you don't, you can use only() to retrieve only the fields provided as arguments:

Event.objects.only("title")

Using Django's get_object_or_404 shortcut


Django tip:

You can use get_object_or_404 to raise the Http404 exception when the object doesn't exist instead of handling DoesNotExist and raising Http404 by yourself.

👇

from django.http import Http404
from django.shortcuts import get_object_or_404


def my_view(request):
    obj = get_object_or_404(MyModel, pk=1)


# the above is equivalent to
def my_view(request):
    try:
        obj = MyModel.objects.get(pk=1)
    except MyModel.DoesNotExist:
        raise Http404("No MyModel matches the given query.")

Find the union of two Django querysets


Django tip:

You can use | to create a union of multiple queries.

👇

by_username = User.objects.filter(username="John")
by_name = User.objects.filter(full_name="John")
users = by_username | by_name

Django REST Framework - Combining and Excluding Permission Classes


Did you know?

You can combine permissions in Django REST Framework using &, |, and ~.

👇

class MyModelViewSet(viewsets.ModelViewSet):
    permission_classes = IsAuthenticated & (IsAdminUser | IsFaculty | ReadOnly)


class MyModelViewSet(viewsets.ModelViewSet):
    permission_classes = ~IsStudent & IsAuthenticated

For more, check out the Combining and Excluding Permission Classes section from Custom Permission Classes in Django REST Framework.

Custom field validators in Django


Did you know?

In Django, you can add custom validators to your model fields

For example, you can validate that price is always greater than 0👇

from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _


def validate_greater_than_zero(value):
    if value <= 0:
        raise ValidationError(
            _("%(value)s is not greater than zero."),
            params={"value": value},
        )


class Book(models.Model):
    title = models.CharField(max_length=120)
    price = models.DecimalField(validators=[validate_greater_than_zero])

Change a model field name in Django REST Framework


Django tip:

You can rename the model field inside the serializer by using the source for the selected field.

For example, the is_active field from the model can be returned as active👇

# models. py
from django.contrib.auth.models import User
from django.db import models


class UserProfile(models.Model):
    user = models.OneToOneField(to=User, on_delete=models.CASCADE)
    bio = models.TextField()
    birth_date = models.DateField()

    def __str__(self):
        return f"{self.user.username} profile"


# serializers.py
from rest_framework import serializers


class UserSerializer(serializers.ModelSerializer):
    active = serializers.BooleanField(source="is_active")

    class Meta:
        model = User
        fields = ["id", "username", "email", "is_staff", "active"]

Django - custom user model


Django Tip:

Use a custom user model when starting a project

When starting a new project, set up a custom user model. This model behaves just like the default user model, but you'll be able to customize it in the future.

https://testdriven.io/blog/django-custom-user-model/

# users/models.py

from django.contrib.auth.models import AbstractUser


class CustomUser(AbstractUser):
    pass


# users/adming.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .models import CustomUser

admin.site.register(CustomUser, UserAdmin)


# settings.py

AUTH_USER_MODEL = "users.CustomUser"