Skip to content

Instantly share code, notes, and snippets.

@pvanfas
Last active July 25, 2024 03:37
Show Gist options
  • Save pvanfas/6a31ec1a08e2b06e6b4735d3b263c822 to your computer and use it in GitHub Desktop.
Save pvanfas/6a31ec1a08e2b06e6b4735d3b263c822 to your computer and use it in GitHub Desktop.

Django Class-based views

A view is a callable which takes a request and returns a response. This can be more than just a function, and Django provides an example of some classes which can be used as views. These allow you to structure your views and reuse code by harnessing inheritance and mixins. There are also some generic views for tasks which we’ll get to later, but you may want to design your own structure of reusable views which suits your use case

from django.db import models
from main.models import BaseModel
from django.core.validators import MinValueValidator
from decimal import Decimal
from django.urls import reverse_lazy
class Unit(BaseModel):
code = models.CharField(max_length=50,unique=True)
name = models.CharField(max_length=128)
description = models.TextField(blank=True,null=True)
is_active = models.BooleanField(default=True)
def get_absolute_url(self):
return reverse_lazy('products:unit_detail', kwargs={'pk': self.pk})
def get_update_url(self):
return reverse_lazy('products:unit_update', kwargs={'pk': self.pk})
def get_delete_url(self):
return reverse_lazy('products:unit_delete', kwargs={'pk': self.pk})
def __str__(self):
return str(f"{self.code} - {self.name}")
from django.urls import reverse_lazy
from django.views.generic import ListView, DetailView, TemplateView
from django.views.generic.edit import FormView, CreateView, UpdateView, DeleteView
from .models import Unit
from django.http.response import HttpResponse
import json
class UnitListView(ListView):
queryset = Unit.objects.filter(is_active=True)
template_name = "app/common/object_list.html"
class UnitDetailView(DetailView):
queryset = Unit.objects.filter(is_active=True)
template_name = "app/common/object_detail.html"
class UnitCreateView(CreateView):
model = Unit
template_name = "app/common/object_form.html"
fields = '__all__'
class UnitUpdateView(UpdateView):
model = Unit
template_name = "app/common/object_form.html"
fields = '__all__'
class UnitDeleteView(DeleteView):
model = Unit
template_name = 'app/common/confirm_delete.html'
success_url = reverse_lazy('products:unit_list')
from django.urls import path
from . import views
from django.contrib.auth.decorators import login_required
app_name = 'products'
urlpatterns = [
path('units/', login_required(views.UnitListView.as_view()),name='unit_list'),
path('units/new/', login_required(views.UnitCreateView.as_view()),name='unit_new'),
path('units/<str:pk>/', login_required(views.UnitDetailView.as_view()),name='unit_detail'),
path('units/update/<str:pk>/', login_required(views.UnitUpdateView.as_view()),name='unit_update'),
path('units/delete/<str:pk>/', login_required(views.UnitDeleteView.as_view()),name='unit_delete'),
]
from django.contrib import admin
from django.apps import apps
app = apps.get_app_config('products')
for model_name, model in app.models.items():
admin.site.register(model)
{% extends 'app/base.html' %}
{% load static i18n crispy_forms_tags %}
{% block title %}Delete "{{object}}"{% endblock %}
{% block content %}
<div class="page-header">
<h3 class="page-title"> Delete "{{object}}"</h3>
</div>
<div class="row">
<div class="col-md-6 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<form method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<div class="buttons mt-5">
<button type="submit" class="btn btn-gradient-danger">{% trans "Yes, Delete." %}</button>
<button type="button" onclick="history.back()" class="btn btn-light btn-outline-secondary">{% trans "No, Take me back" %}</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
<!-- app/common/object_detail.html -->
{% extends 'app/base.html' %}
{% load static i18n crispy_forms_tags %}
{% block title %}{{title}}{% endblock %}
{% block content %}
<div class="page-header">
<h3 class="page-title">{{object}}</h3>
</div>
<div class="row">
<div class="col-md-12 grid-margin stretch-card">
<div class="card">
<div class="card-header">
<h4 class="card-title">{{object}}</h4>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table-hover border" style="width:100%;">
<tbody>
<tr>
<td> {{object.code}} </td>
<td> {{object.name}} </td>
<td> {{object.description}} </td>
<td> {{object.is_active}} </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card-footer">
<div class="">
<a href="{{object.get_absolute_url}}" class="btn btn-sm btn-light btn-outline-primary mr-2">{% trans "View" %}</a>
<a href="{{object.get_update_url}}" class="btn btn-sm btn-light btn-outline-info mr-2">{% trans "Edit" %}</a>
<a href="{{object.get_delete_url}}" class="btn btn-sm btn-light btn-outline-danger">{% trans "Delete" %}</a>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
{% extends 'app/base.html' %}
{% load static i18n crispy_forms_tags %}
{% block title %}{{object}}{% endblock %}
{% block javascript %}
{{form.media}}
{% endblock javascript %}
{% block content %}
<div class="page-header">
<h3 class="page-title"> {{object}}</h3>
</div>
<div class="row">
<div class="col-md-6 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<form class="forms-sample" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{form|crispy}}
<button type="submit" class="btn btn-gradient-primary mr-2">{% trans "Save" %}</button>
<button type="button" onclick="history.back()" class="btn btn-light btn-outline-secondary">{% trans "Cancel" %}</button>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
<!-- app/common/object_list.html -->
{% load static %}
{% block title %}{{title}}{% endblock %}
{% block content %}
<div class="page-header">
<h3 class="page-title">
<span class="page-title-icon bg-gradient-primary text-white mr-2">
<i class="mdi mdi-home"></i>
</span> {{title}}
</h3>
{% if request.user.is_superuser %}
<nav aria-label="breadcrumb">
<ul class="breadcrumb">
<li class="breadcrumb-item active" aria-current="page">
<a href="{{new_link}}" class="btn btn-lg btn-gradient-primary">New {{title}}</a>
</li>
</ul>
</nav>
{% endif %}
</div>
<div class="row">
<div class="col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
{% if object_list %}
<div class="table-responsive">
<table class="table table-bordered table-hover border" style="width:100%;">
<thead>
<tr>
<th> # </th>
<th> name </th>
{% if request.user.is_superuser %}<th> Actions </th>{% endif %}
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<td>{{forloop.counter}}</td>
<td> {{object.name}} </td>
{% if request.user.is_superuser %}
<td>
<a href="{{object.get_update_url}}" class="btn btn-sm btn-circle btn-info"><i class="mdi mdi-pencil"></i></a>
<a href="{{object.get_delete_url}}" class="btn btn-sm btn-circle btn-danger"><i class="mdi mdi-delete"></i></a>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<small class="mb-0">No {{title}} exists.</small>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock content %}
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center mb-0">
{% if is_paginated %}
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% endif %}
{% for i in page_obj.paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active">
<span class="page-link">{{ i }} <span class="sr-only"></span></span>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% endif %}
{% endif %}
</ul>
</nav>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment