Generic Class-Based Views
Buraq provides Django-style generic views for the most common patterns.
ListView
Section titled “ListView”Display a list of objects:
from buraq.views.generic import ListView
class PostListView(ListView): model = Post template_name = "posts/list.html" paginate_by = 10 # enables pagination ordering = ["-created_at"]
# Template context: object_list, post_list, paginator, page_obj, is_paginatedCustom queryset:
class PublishedPostListView(ListView): model = Post template_name = "posts/list.html"
async def get_queryset(self): return await Post.objects.filter(is_published=True).order_by("-created_at")DetailView
Section titled “DetailView”Display a single object by pk or slug:
class PostDetailView(DetailView): model = Post template_name = "posts/detail.html" pk_url_kwarg = "pk" # URL param name (default: "pk")
# Template context: object, post (model name lowercased)CreateView
Section titled “CreateView”Display a form and create a new object on POST:
class PostCreateView(CreateView): model = Post form_class = PostForm template_name = "posts/form.html" success_url = "/posts/"UpdateView
Section titled “UpdateView”Display a pre-filled form and update an existing object on POST:
class PostUpdateView(UpdateView): model = Post form_class = PostForm template_name = "posts/form.html" success_url = "/posts/"DeleteView
Section titled “DeleteView”Confirm and delete an object:
class PostDeleteView(DeleteView): model = Post template_name = "posts/confirm_delete.html" success_url = "/posts/"TemplateView
Section titled “TemplateView”Render a template with optional extra context:
from buraq.views.generic import TemplateView
class AboutView(TemplateView): template_name = "about.html" extra_context = {"title": "About Us"}RedirectView
Section titled “RedirectView”from buraq.views.generic import RedirectView
urlpatterns = [ get("/old-url/", RedirectView.as_view(url="/new-url/", permanent=True)),]preserve_request
Section titled “preserve_request”By default a redirect responds with 302 Found (or 301 Moved Permanently), which instructs the browser to repeat the request as GET regardless of the original method. Set preserve_request = True to return 307 Temporary Redirect (or 308 Permanent Redirect) instead, preserving the original HTTP method:
urlpatterns = [ post( "/submit/", RedirectView.as_view( url="/new-submit/", preserve_request=True, # 307 — client repeats the POST ), ),]permanent |
preserve_request |
Status |
|---|---|---|
False (default) |
False (default) |
302 Found |
True |
False |
301 Moved Permanently |
False |
True |
307 Temporary Redirect |
True |
True |
308 Permanent Redirect |
put(), patch(), and delete() handlers are also supported so that non-GET verbs receive the correct redirect response.
FormView
Section titled “FormView”Handle a form’s GET/POST cycle without tying it to a model. See FormView for the full reference.
from buraq.views.generic import FormView
class ContactView(FormView): template_name = "contact.html" form_class = ContactForm success_url = "/thanks/"
async def form_valid(self, request, form): await send_contact_email(form.cleaned_data) return redirect(self.success_url)Date archive views
Section titled “Date archive views”Filter objects by date field. All archive views share date_field (default "created_at") and allow_future.
from buraq.views.generic import ( YearArchiveView, MonthArchiveView, WeekArchiveView, DayArchiveView, TodayArchiveView, ArchiveIndexView, DateDetailView,)YearArchiveView / MonthArchiveView
Section titled “YearArchiveView / MonthArchiveView”class PostYearView(YearArchiveView): model = Post date_field = "published_on"
class PostMonthView(MonthArchiveView): model = Post date_field = "published_on"
urlpatterns = [ get("/<int:year>", PostYearView.as_view()), get("/<int:year>/<int:month>", PostMonthView.as_view()),]WeekArchiveView
Section titled “WeekArchiveView”List objects for an ISO week number.
class PostWeekView(WeekArchiveView): model = Post date_field = "published_on"
# URL: /2024/week/12get("/<int:year>/week/<int:week>", PostWeekView.as_view())DayArchiveView
Section titled “DayArchiveView”class PostDayView(DayArchiveView): model = Post date_field = "published_on"
# URL: /2024/3/15get("/<int:year>/<int:month>/<int:day>", PostDayView.as_view())TodayArchiveView
Section titled “TodayArchiveView”No URL parameters needed — always uses today’s date.
class TodayPostsView(TodayArchiveView): model = Post date_field = "published_on"
get("/today", TodayPostsView.as_view())ArchiveIndexView
Section titled “ArchiveIndexView”Top-level archive — provides a list of all distinct years in date_list.
class PostArchiveView(ArchiveIndexView): model = Post date_field = "published_on" template_name = "posts/archive.html" # context: date_list (list of year dates)
get("/archive", PostArchiveView.as_view())DateDetailView
Section titled “DateDetailView”Retrieve a single object by year/month/day + pk or slug.
class PostDateDetailView(DateDetailView): model = Post date_field = "published_on" template_name = "posts/detail.html"
get("/<int:year>/<int:month>/<int:day>/<int:pk>", PostDateDetailView.as_view())Auth mixins
Section titled “Auth mixins”Add access control to any CBV by mixing in before the view class. See Auth Mixins for the full reference.
from buraq.views.mixins import LoginRequiredMixin, PermissionRequiredMixin
class PostCreateView(LoginRequiredMixin, CreateView): model = Post form_class = PostForm success_url = "/posts/"
class PostPublishView(PermissionRequiredMixin, UpdateView): model = Post permission_required = "blog.publish_post" success_url = "/posts/"Overriding context
Section titled “Overriding context”class PostDetailView(DetailView): model = Post template_name = "posts/detail.html"
async def get_context_data(self, **kwargs): ctx = await super().get_context_data(**kwargs) ctx["related"] = await Post.objects.filter(is_published=True).limit(3) return ctxURL registration
Section titled “URL registration”urlpatterns = [ get("/", PostListView.as_view(), name="post_list"), get("/<str:slug>", PostDetailView.as_view(), name="post_detail"), get("/new", PostCreateView.as_view(), name="post_create"), post("/new", PostCreateView.as_view()), get("/<int:pk>/edit", PostUpdateView.as_view(), name="post_update"), post("/<int:pk>/edit", PostUpdateView.as_view()), get("/<int:pk>/delete", PostDeleteView.as_view(), name="post_delete"), post("/<int:pk>/delete", PostDeleteView.as_view()),]