Last active
November 23, 2016 14:15
-
-
Save craigderington/8b22a727c0c72a5bf3d727e0732b4c20 to your computer and use it in GitHub Desktop.
Solved: Django Tables2 and AJAX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% 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" %} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'), | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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