Skip to content

Instantly share code, notes, and snippets.

@craigderington
Last active November 23, 2016 14:15
Show Gist options
  • Save craigderington/8b22a727c0c72a5bf3d727e0732b4c20 to your computer and use it in GitHub Desktop.
Save craigderington/8b22a727c0c72a5bf3d727e0732b4c20 to your computer and use it in GitHub Desktop.
Solved: Django Tables2 and AJAX
from django.contrib.auth.models import User
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import Q
class Alert(models.Model):
SYSTEM_ALERT = 'system_alert'
USER_ALERT = 'user_alert'
CUSTOMER_ALERT = 'customer_alert'
TYPE_CHOICES = (
(SYSTEM_ALERT, 'System Generated Alert'),
(USER_ALERT, 'User Generated Alert'),
(CUSTOMER_ALERT, 'Customer Generated Alert')
)
type = models.CharField(max_length=255, null=False, blank=False, choices=TYPE_CHOICES)
customer = models.ForeignKey(Customer, null=False, blank=False)
dealer = models.ForeignKey(Dealer, null=True, blank=True)
data = models.TextField(null=False, blank=False, default='{}')
dt_event = models.DateTimeField(null=True)
is_read = models.BooleanField(null=False, blank=False, default=False)
def __unicode__(self):
unread = '[UNREAD] ' if not self.is_read else ''
return str('%s%s: %s on %s' % (unread, self.customer.id, self.get_type_display(), self.dt_event.strftime('%b %d, %Y')))
class Meta:
ordering = ('-dt_event', 'customer')
{% extends "base.html" %}
{% load bootstrap3 %}
{% load querystring from django_tables2 %}
{% load title from django_tables2 %}
{% load trans blocktrans from i18n %}
{% load fontawesome %}
{% block "title" %}Manage Alerts{% endblock "title" %}
{% block "content" %}
{% if messages %}
{% for message in messages %}
<div class="messages alert alert{% if message.tags == 'error' %}-danger{% else %}-{{ message.tags }}{% endif %}">
<b>{% if message.tags == "success" %}{% fontawesome_icon 'check-circle' %} Message: {% elif message.tags == "error" %}{% fontawesome_icon 'warning' %} Error:{% endif %}</b> {{ message }}
</div>
{% endfor %}
{% endif %}
{% if table.page %}
<div class="table-container">
{% endif %}
{% block table %}
<div class="table-responsive" id="alerts" style="margin-top:-20px;">
<table class="table table-hover table-bordered table-striped"{% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
{% block table.thead %}
<thead>
<tr>
<th colspan="3">
<h3><i class="fa fa-warning"></i> Manage Alerts </h3>
</th>
<th colspan="3">
<form method="post" class="form-inline form-search pull-right">
{% csrf_token %}
<div>
<input id="search_form_id" name="search" type="text" class="form-control col-md-4" placeholder="Search by Alert Type or Customer Name"{% if search %} value="{{ search }}"{% endif %} size="30">
<button type="submit" class="btn btn-small btn-dark"><i class="fa fa-search"></i> Search</button>
</div>
</form>
</th>
</tr>
<tr class="primary">
{% for column in table.columns %}
{% if column.orderable %}
<th {{ column.attrs.th.as_html }}><a href="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}">{{ column.header|title }}</a></th>
{% else %}
<th {{ column.attrs.th.as_html }}>{{ column.header|title }}</th>
{% endif %}
{% endfor %}
</tr>
</thead>
{% endblock table.thead %}
{% block table.tbody %}
<tbody>
{% for row in table.page.object_list|default:table.rows %} {# support pagination #}
{% block table.tbody.row %}
<tr {{ row.attrs.as_html }}>
{% for column, cell in row.items %}
<td {{ column.attrs.td.as_html }}>{{ cell }}</td>
{% endfor %}
</tr>
{% endblock table.tbody.row %}
{% empty %}
{% if table.empty_text %}
{% block table.tbody.empty_text %}
<tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
{% endblock table.tbody.empty_text %}
{% endif %}
{% endfor %}
</tbody>
{% endblock table.tbody %}
{% block table.tfoot %}
<tfoot></tfoot>
{% endblock table.tfoot %}
</table>
</div>
{% endblock table %}
{% if table.page %}
{% block pagination %}
{% bootstrap_pagination table.page url=request.get_full_path %}
{% endblock pagination %}
</div>
{% endif %}
{% endblock "content" %}
{% block "js" %}
{{ block.super }}
<script type="text/javascript">
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
$('#alerts a.dismiss').on('click', function() {
var $row = $(this).closest('tr'),
pk = $row.attr('data-alert-pk');
if (!pk) return;
var url = '{% url 'dismiss-alert' %}';
$.ajax({
url: url,
headers: {
'X-CSRFToken': csrftoken
},
method: 'POST',
data: {
'pk': pk
}
}).done(function() {
$row.remove();
}).fail(function() {
alert('Error dismissing alert');
});
});
</script>
{% endblock "js" %}
from reporting.models import Alert
import django_tables2 as tables
from django_tables2.utils import A
action_template = """
<a href="#" class="dismiss" title="Clear Alert">
<i class="fa fa-times-circle fa-2x text-danger"></i>
</a>
"""
class AlertsTable(tables.Table):
alert_action = tables.TemplateColumn(action_template)
class Meta:
model = Alert
row_attrs = {
'data-alert-pk': lambda record: record.id
}
empty_text = "There are no active alerts to display in this view."
from django.conf.urls import url
from reporting import views
from django.views.static import serve
from config.settings import base as settings
urlpatterns = [
url(r'^dashboard/$', views.dashboard, name='dashboard'),
url(r'^customers/$', views.customers, name='customers'),
url(r'^alerts/$', views.alerts, name='alerts'),
url(r'^dismiss-alert$', views.customer_management_dismiss_alert,
name='dismiss-alert'),
]
from reporting.models import Alert
from reporting.tables import AlertsTable
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.core.paginator import PageNotAnInteger, EmptyPage
from django.core.urlresolvers import reverse
from django.core.exceptions import ObjectDoesNotExist
from django.db.models.query_utils import Q
from django.http import HttpResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.template import Context, loader, TemplateDoesNotExist
from django.template.context import RequestContext
from django_tables2 import RequestConfig
@login_required
def alerts(req):
req.session['form_data'] = None
search = None
alerts = Alert.objects.filter(dealer=req.dealer.id, is_read=False)
if req.method == 'POST':
search = req.POST.get('search', None)
if search:
alerts = alerts.filter(
Q(customer__customer_name__icontains=search) |
Q(customer__customer_number__icontains=search)
)
# render the alerts table with django-tables
table = AlertsTable(alerts)
RequestConfig(req, paginate={'per_page': 30}).configure(table)
return render(
req,
'reporting-alerts.html', {
'table': table,
'alerts': alerts,
'search': search
}
)
def customer_management_dismiss_alert(req):
"""This view is intended to use via AJAX"""
alert_pk = req.POST.get('pk', None)
alert = get_object_or_404(req.customer.alert_set, pk=alert_pk)
alert.is_read = True
alert.save()
return HttpResponse('')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment