Pinax Patterns Cheat Sheet
Abbreviations
An object
is sometimes also referred to as obj
.
A queryset is sometimes referred to as qs
.
Context data is sometimes referred to as ctx
.
Creating a Class
Creating a Class in Python 2
A class is created in Python 2.
class ClassName(object):
Creating a Class in Python 3
A class is created in Python 3.
class ClassName():
Creating a Model Class
A model class called ModelClass
is created.
class ModelClass(models.Model):
Creating a Class Compatible with Python 2 and 3
A model class called ModelClass
that is compatible with both Python 2 and 3 is created.
@python_2_unicode_compatible
class ModelClass(models.Model):
Model Class Inheritance
Another model class called InheritingModelClass
is created that inherits the attributes and methods of ModelClass
.
class InheritingModelClass(ModelClass):
Form Class Inheritance
A form class called FormClass
is created.
class FormClass(forms.ModelForm):
Form Class Inheritance
Another form class called InheritingFormClass
is created that inherits the attributes and methods of FormClass
.
class InheritingFormClass(FormClass):
ModelForm
class FormClass(forms.ModelForm):
class Meta:
model = ModelClass
fields = [
"field",
"field"
]
Form Instantiation
class FormClass(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.variable = kwargs.pop("keyword")
super(FormClass, self).__init__(*args, **kwargs)
Importing
Model Classes
Model classes can be imported for use in files other than models.py.
from .models import ModelClass, AnotherModelClass
Form Classes
Form classes can be imported for use in files other than forms.py.
from .forms import FormClass, AnotherFormClass
View Classes
View classes can be imported for use in files other than views.py.
from .views import ViewClass, AnotherViewClass
Models
ForeignKey Model Field
Typical ForeignKey User syntax
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Alternate ForeignKey User syntax
user = models.ForeignKey(User, on_delete=models.CASCADE)
Typical ForeignKey non-User syntax (model name and RelatedModel name are often the same)
model = models.ForeignKey(RelatedModel, on_delete=models.CASCADE)
OneToOneField Model Field
Typical OneToOneField User syntax
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Typical OneToOneField non-User syntax (model name and RelatedModel name are often the same)
model = models.OneToOneField(RelatedModel, on_delete=models.CASCADE)
ManyToManyField Model Field
related_name
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="Related Name", on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="+", on_delete=models.CASCADE)
Other Model Fields
CharField
character_field_example = models.CharField(max_length=100)
character_field_example = models.CharField(help_text="Help text")
character_field_example = models.CharField(default="Default")
TextField
text_field_example = models.TextField()
text_field_example = models.TextField(help_text="Help text")
BooleanField
boolean_field_example = models.BooleanField(default=True)
boolean_field_example = models.BooleanField(default=False)
DateTimeField
date_time_field_example = models.DateTimeField()
date_time_field_example = models.DateTimeField(default=timezone.now)
IntegerField
integer_field_example = models.IntegerField()
integer_field_example = models.IntegerField(default=0)
integer_field_example = models.IntegerField(max_length=5)
PositiveIntegerField
positive_interger_field_example = models.PositiveIntegerField()
positive_interger_field_example = models.PositiveIntegerField(default=0)
DecimalField
decimal_field_example = models.DecimalField(decimal_places=2, max_digits=10)
CASCADE Versus SET_NULL
model = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
model = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL)
Verbose Name as Model Field
Verbose name through model field (not Meta class)
example_field = models.Field(_("Verbose Name"))
example_field = models.Field(verbose_name=_("Verbose Name"))
Meta Class
Alternate verbose name syntax
class Meta:
verbose_name = "Verbose Name"
verbose_name_plural = "Verbose Names"
Alternate verbose name syntax
class Meta:
verbose_name = _("Verbose Name")
verbose_name_plural = _("Verbose Names")
Unique together
class Meta:
unique_together = [
()
]
Ordering
class Meta:
ordering =
String Representation of the Object
In Python 2, string returned as bytes
def __str__(self):
return
In Python 2, string returned as text (no longer used in Python 3)
def __unicode__(self):
return
In Python 3 or 2, returns printable string representation of object.
def __repr__(self):
return
Using Python 3 and 2, support for Python 2 unicode
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class ModelClass(models.Model):
def __str__(self):
return
String Formatting
Simple string formatting
def __str__(self):
return "{} - {}".format(self.variable, self.another_variable)
String formatting using positional arguments
def __str__(self):
return "{0} - {1}".format(self.variable, self.another_variable)
Get Absolute URL
Simple get absolute URL
def get_absolute_url(self):
return
def get_absolute_url(self):
return reverse("pinax_app:view_name", args=[self.pk])
def get_absolute_url(self):
return reverse("pinax_app:view_name", args=[self.slug])
def get_absolute_url(self):
return reverse("pinax_app:view_name", args=[self.path])
Model Methods and Attributes
Model Attributes
Model Methods
Method
def method(self):
return
Class method
@classmethod
def class_method(cls):
return
Class method with parameters
@classmethod
def class_method_name(cls, parameters...):
return
Property method
@property
def property_method(self):
return
Cached property method
@cached_property
def cached_property_method(self):
return
Property and cached attribute method
@property
@cached_attribute
def property_cached_attribute_method(self):
return
URLs
Project URLs
Typical project-level urls.py patterns
from django.conf import settings
from django.urls import include, path
from django.conf.urls.static import static
from django.views.generic import TemplateView
from django.contrib import admin
urlpatterns = [
path("", TemplateView.as_view(template_name="homepage.html"), name="home"),
path("account/", include("account.urls")),
path("app/", include("pinax.app.urls", namespace="pinax_app")),
path("admin/", admin.site.urls)
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Apps URLs
App URLs vary based on the project.
Typical app-level urls.py patterns using generic class-based views.
from django.conf.urls import url
from .views import (
ListViewName,
CreateViewName,
DetailViewName,
UpdateViewName,
DeleteViewName,
)
app_name = "pinax_app"
urlpatterns = [
url(r"^page/$", ListViewNameListView.as_view(), name="list_view_name"),
url(r"^page/create/$", CreateViewNameCreateView.as_view(), name="create_view_name"),
url(r"^page/(?P<pk>\d+)/$", DetailViewNameDetailView.as_view(), name="detail_view_name"),
url(r"^page/(?P<pk>\d+)/update/$", UpdateViewNameUpdateView.as_view(), name="update_view_name"),
url(r"^page/(?P<pk>\d+)/delete/$", DeleteViewNameDeleteView.as_view(), name="delete_view_name"),
]
App URLs Namespace
App URLs will include a namespace to avoid duplication.
app_name = "pinax_app"
Generic, Class-Based Views (CBVs)
Anytime possible, Pinax uses Django's built-in, generic, class-based views to handle common view patterns. Pinax starter project homepages are rendered via TemplateView.
View that Returns Neither a Queryset nor Object
- FormView
View that Returns a Queryset
- ListView
Views that Return a Single Object, Sometimes by Filtering a Queryset
- DetailView
- DateDetailView
- CreateView
- UpdateView
- DeleteView
Generic, Class-Based Views Importing
from django.views.generic import (
CreateView,
DeleteView,
DetailView,
FormView,
ListView,
TemplateView
UpdateView,
View,
)
from django.views.generic.dates import DateDetailView
Alternatively
from django.views.generic import DetailView
from django.views.generic.base import TemplateView, View
from django.views.generic.dates import DateDetailView
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
from django.views.generic.list import ListView
Base View
TemplateView Subclassing
TemplateView is sometimes subclassed in views.py.
class TemplateViewName(TemplateView):
template_name = "pinax/directory/template.html"
List and Detail Views
ListView
ListView returns a queryset rendered in a template using context_object_name
.
class ListViewName(ListView):
model = ModelName
context_object_name = "Context Name"
template_name = "pinax/directory/template.html"
Querysets sometimes require pagination or search functionality.
paginate_by = settings.PINAX_BLOG_PAGINATE_BY
paginate_by = 50
search_parameter = "q"
DetailView
DetailView returns single object detail rendered in a template using context_object_name
.
class DetailViewName(DetailView):
model = ModelName
context_object_name = "Context Name"
template_name = "pinax/directory/template.html"
DateDetailView
DateDetailView returns single object detail from a single date rendered in a template.
class DateDetailViewName(DateDetailView):
model = Post
month_format = "%m"
example_date_field = "published"
template_name = "pinax/directory/template.html"
Generic Editing Views
FormView
FormView displays a form in a template and renders a response.
class FormViewName(FormView):
form_class = FormName
template_name = "pinax/directory/template.html"
redirect_field_name = "next"
CreateView
CreateView is used to create a new object, with a response rendered in a template.
class CreateViewName(CreateView):
model = ModelName
form_class = FormName
template_name = "pinax/directory/template.html"
success_url = reverse_lazy("pinax_app:view")
UpdateView
UpdateView is used to update an existing object, with a response rendered in a template using context_object_name
.
class UpdateViewName(UpdateView):
model = ModelName
form_class = FormName
context_object_name = "Context Name"
template_name = "pinax/directory/template.html"
success_url = reverse_lazy("pinax_app:view")
DeleteView
DeleteView is used to delete an existing object, with a response rendered in a template.
class DeleteViewName(DeleteView):
model = ModelName
template_name = "pinax/directory/template.html"
success_url = reverse_lazy("pinax_app:view")
Views Returning Objects (Create, Detail, Update, Delete Views)
Common options
pk_url_kwarg = "post_pk"
slug_url_kwarg = "slug_url_kwarg"
slug_field = "slug_field"
Data Structures
Lists
- A queryset is a list of objects.
Dictionaries
- Model fields ("keys") and values
- Form fields ("keys") and values, including cleaned data
- Context data variables ("keys") and values, rendered in a template
- JSON data serialized
Accessing Values
The dictionary "key" corresponds to the value
dictionary["key"] = value
Common View Methods
Dispatch
Used to decorate every instance of a class-based view
def dispatch(self, *args, **kwargs):
return super(ViewName, self).dispatch(*args, **kwargs)
Get Queryset
Returns a list of objects that the view will display
def get_queryset(self):
Get Object
Returns the single object that the view will display.
def get_object(self, queryset=None):
Get Context Data
In a class-based view, context is passed to the template. Here the ```get_context_data() is overridden. The existing context is fetched, updated with additional variable(s) to pass to the template, and the updated context returned.
def get_context_data(self, **kwargs):
context = super(ViewName, self).get_context_data(**kwargs)
context.update({
})
return context
Get
def get(self, request, *args, **kwargs):
Render to Response
def render_to_response(self, context, **response_kwargs):
Additional Common Generic Editing View Methods
Form Valid
def form_valid(self, form):
Form Invalid
def form_invalid(self, form):
Get Form Class
Returns the form class to instantiate
def get_form_class(self):
Get Form Kwargs
Returns a dictionary of kwargs that will be passed to the form _init_
def get_form_kwargs(self):
kwargs = super(ViewName, self).get_form_kwargs()
kwargs.update({
})
return kwargs
Get Initial
Returns a dictionary of initial data for the form, with the field name as key and the value as the initial value on the form for the user
def get_initial(self):
initial = super(ViewName, self).get_initial()
initial.update({
})
return initial
Get Success URL
def get_success_url(self):
Get Template Names
def get_template_names(self):
Post
def post(self, request, *args, **kwargs):
Delete
Request and Response Objects
HTTPS and JSON Importing
from django.http import (
Http404,
HttpResponse,
HttpResponseBadRequest,
HttpResponseForbidden,
HttpResponseNotAllowed,
HttpResponseRedirect,
JsonResponse,
)
HTTPS and JSON Methods
Example: Form Valid
Example: Form Invalid
def form_invalid(self, form):
if self.request.is_ajax():
data = {
"status": "ERROR",
"errors": form.errors
}
return JsonResponse(data)
return HttpResponseRedirect(self.get_secure_redirect_to())
def form_invalid(self, form):
if self.request.is_ajax():
data = {
"status": "ERROR",
"errors": form.errors,
"html": render_to_string("pinax/directory/_form.html", {
"form": form,
"obj": self.content_object
}, request=self.request)
}
return JsonResponse(data)
return HttpResponseRedirect(self.get_secure_redirect_to(self.content_object))
Sessions
User
AnonymousUser
Ajax
JsonResponse
if self.request.is_ajax():
if request.is_ajax():
Protected Views
Mixins
Options commonly used in FormView, DetailView, CreateView, UpdateView, DeleteView
class ViewName(PasswordMixin, GenericViewType):
class ViewName(LoggedInMixin, GenericViewType):
class ViewName(LoginRequiredMixin, GenericViewType):
class ViewName(ProtectedView, GenericViewType):
Decorators
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required
@login_required
@permission_required()
More Importing
Additional Custom Imports
from .decorators import decorator_name
from .hooks import hookset
from .signals import signal_name
Django User Accounts and Stripe Imports
from account.models import AccountModel