Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@JohnStuartRutledge
Last active January 13, 2024 16:33
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save JohnStuartRutledge/c24fffc4ac37b134f202 to your computer and use it in GitHub Desktop.
Save JohnStuartRutledge/c24fffc4ac37b134f202 to your computer and use it in GitHub Desktop.

Django Idioms

General Tips

  • put methods that apply to a single instance of a Model on the model class itself
  • put methods meant to query against a Models entire table that models corresponding managers.py file.
  • if a models.py file gets too long to manage then create a models directory and place an __init__ file in it.
  • try to avoid using signals, but if you must then put them in a signals.py file

when to use null=True vs blank=True

class MyModel(models.Model):
    a = models.DateTimeField(null=True)  # blank fields get stored as NULL in your DB column
    b = models.DateTimeField(blank=True) # determines if field will be required in forms

Alwasy be specific in the type of error you want to catch in your try/catch statements, AKA errors should never pass silently unless explicitly silenced.

# this is BAD
try:
    x = MyModel.objects.all()
except Exception:
    pass

# this is GOOD
try:
    x = MyModel.objects.all()
except MyModel.DoesNotExist:
    # do something ...
    

Django ORM Tips

exists()

.exists() is used to check if the queryset returned anything.

iterator()

.iterator() should always be used when you want to iterate over the results of a queryset only once.

select_related()

.select_related() For use in forward ForeignKey, forward OneToOne, and backward OneToOne relationships.

prefetch_related()

.prefetch_related Performs a separate lookup for each relationship and does the 'joining' in Python. For use with ManyToMany, ManyToOne, GenericRelations, and GenericForeignKey relations only.

Note - this gets ignored if you're using the .iterator() method

defer()

.defer() if you're using the results of a queryset in a situation where you might not need particular fields for the initial fetch of data, then you can pass the names of a fields you don't immediately need (aka you can defer them). This saves the expensive processing power spent converting the fields to Python objects.

NoodleUsers.object.defer("joined_date")

bulk_create()

.bulk_create is used to efficently create multiple items at once.

Question.object.bulk_create([
	Question(question='what'),
	Question(question='where'),
	Question(question='when'),
])

get_or_create()

.get_or_create() is a useful shortcut method

# replaces this
try:
	u = Person.objects.get(name='bob')
except Person.DoesNotExist:
	p = Person(name='bob')
	p.save()

# with this instead:
p, create = Person.objects.get_or_create(name='bob')

Noodle 3rd Party Libraries

Use Django-Model-Utils TimeStampedModel when you want to add a created and modified datetime field to a model.

from model_utils.models import TimeStampedModel

class YourModel(TimeStampedModel):
   	pass

Use Django-Braces Access Mixins when you want to add mixins to your views that restrict access to certain views.

For example, restrict a view to superuser use only you would do:

from django.views import TemplateView
from braces.views import SuperuserRequiredMixin

class SomeView(SuperuserRequiredMixin, TemplateView):
    template_name = u"path/to/template.html"

Django-Extensions

  • Why you should use runserver_plus instead of builtin runserver
  • Why you should use shell_plus instead of builtin shell
  • When the sqldiff command is useful, etc

Templating Conventions

Try to stick to MVC standards by keeping as much business logic out of templates as you can.

Try to avoid processing large datasets in templates. For example:

<!--this is bad-->
{% for usr in NoodleUsers %}
    {% if usr.is_staff %} ... {% endif %}
{% endfor %}

Make use of the Django-Absolute template tag when creating anchor tags:

<a href='{% absolute "index" %}'>link</a>

Unit Tests

  • mock library
  • make as few database calls as you can, they are huge bottleneck
  • Avoid using fixtures when possible. Use FactoryBoy instead.

Debugging

  • how to use ipdb
  • how to use logging and where to find logs
  • how to use Django-Extensions and Django-Debug-Toolbar

South Database Migrations

things to know about South

TODO: explain some of these commands (note dj is an alias for python mange.py

>>> dj migrate --help

>>> dj migrate --list

>>> dj schemamigration <app-name> --initial

>>> dj migrate <app-name>

>>> dj schemamigration <app-name> --auto

>>> dj convert_to_south <app-name>

>>> dj migrate <app-name> <migration-number> --fake

>>> dj migrate --ignore-ghost-migrations

>>> dj migrate --delete-ghost-migrations

>>> dj migrate <app-name> <migration-number> --fake --delete-ghost-migrations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment