Petter Holt Juliussen • Mail | Mastodon | GitHub | Letterboxd

for later reference.

Django

2019-04-04

Shortcuts

The package django.shortcuts collects helper functions and classes that “span” multiple levels of MVC.

render()

Combines a given template with a given context dictionary and returns an HttpResponse object with that rendered text.

render(request, template_name, context=None, content_type=None, status=None, using=None)

Combines a given template with a given context dictionary and returns an HttpResponse object with that rendered text.

return render(request, 'template.html', {
    'foo': 'bar'
})

redirect()

Returns an HttpResponseRedirect to the appropriate URL for the arguments passed.

redirect(to, permanent=False, *args, **kwargs)`
from django.shortcuts import redirect

# Object
obj = MyModel.objects.get(...)
redirect(obj)

# View
redirect('some-view-name', foo='bar')

# URL
redirect('/some/url/')
redirect('https://example.com/')

redirect(reverse('article', args=[article.slug]) + '?edit=true')

QuerySets

Internally, a QuerySet can be constructed, filtered, sliced, and generally passed around without actually hitting the database. No database activity actually occurs until you do something to evaluate the queryset by doing iteration, slicing, pickling/caching or calling repr(), len(), list() or bool().

Iteration

for e in Entry.objects.all():
    print(e.headline)

Slicing

Slicing can be done using Python’s array-slicing syntax. Slicing an unevaluated QuerySet usually returns another unevaluated QuerySet, but Django will execute the database query if you use the “step” parameter of slice syntax, and will return a list.


list()

entry_list = list(Entry.objects.all())

bool()

For testing, or used in an or, and or if statement. If there is at least one result, the QuerySet is True, otherwise False.

if Entry.objects.filter(headline="Test"):
    print("There is at least one Entry with the headline Test")

Methods that return new QuerySets

Django provides a range of QuerySet refinement methods that modify either the types of results returned by the QuerySet or the way its SQL query is executed.

filter()

Returns a new QuerySet containing objects that match the given lookup parameters. Uses field lookups or Q objects for more complex queries.

Entry.objects.filter(pub_date__year=2006)
Entry.objects.all().filter(pub_date__year=2006) # equal using the default manager class

q1 = Entry.objects.filter(headline__startswith="What")
q1.filter(pub_date__gte=datetime.date.today())

exclude()

Returns a new QuerySet containing objects that do not match the given lookup parameters.

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')

order_by()

Methods that do not return QuerySets

The following QuerySet methods evaluate the QuerySet and return something other than a QuerySet.

get()

create()

get_or_create()

A convenience method for looking up an object with the given kwargs (may be empty if your model has defaults for all fields), creating one if necessary.

Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying whether a new object was created.

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)}, # all keywords except "defaults" wil be used in a get() call
)

# equals

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

More complex conditions for the retrieved object can be specified by chaining get_or_create() with filter() and using Q objects. For example, to retrieve Robert or Bob Marley if either exists, and create the latter otherwise:

from django.db.models import Q

obj, created = Person.objects.filter(
    Q(first_name='Bob') | Q(first_name='Robert'),
).get_or_create(last_name='Marley', defaults={'first_name': 'Bob'})

If multiple objects are found, get_or_create() raises MultipleObjectsReturned. If an object is not found, get_or_create() will instantiate and save a new object, returning a tuple of the new object and True.

Managers

A Manager is the interface through which database query operations are provided to Django models. At least one Manager exists for every model in a Django application. By default, Django adds a Manager with the name objects to every Django model class. A manager can be renamed on a per-model basis by defining a class attribute of type models.Manager():

from django.db import models

class Person(models.Model):
    #...
    people = models.Manager()

Using this example model, Person.objects will generate an AttributeError exception, but Person.people.all() will provide a list of all Person objects.

Custom managers

Custom managers can be defined by extending the base Manager class and instantiating the custom Manager in the model. This is done to add extra Manager methods, and/or to modify the initial QuerySet the Manager returns.