I have a problem rendering the HTML element 'live'.
This is my idea, I have a topbar which is included(not extending anything) in the 'base.html' like this :
...
base.html
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Top Bar -->
{% include 'topbar.html' %}
...
And this is the 'topbar.html' itself :
topbar.html
<!-- Topbar -->
{% load static %}
{% load custom_tags %}
{% notification_tag as notifications %}
{% current_time as current_time %}
{% events as all_events %}
...
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
{% if notifications %}
{% for notif in notifications %}
{% if notif.date_to_remind <= current_time %}
<span class="badge badge-danger badge-counter">{{ notifications.count }}</span>
{% endif %}
{% endfor %}
{% endif %}
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Obaveštenja
</h6>
{% for n in notifications %}
{% if not n.viewed %}
<a class="dropdown-item d-flex align-items-center" href="{% url 'notification' n.pk %}">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">{{ n.eluid_posla }}</div>
<span class="font-weight-bold">{{ n.message|slice:"25" }}</span>
</div>
</a>
{% endif %}
{% endfor %}
<a class="dropdown-item text-center small text-gray-500"
href="{% url 'notifications_all' %}">Prikaži
sva obaveštenja</a>
</div>
</li>
...
The idea is, when there is a notification at the exact time, the notification alert show's up (simple red dot from span element) - but without refreshing the page. I managed to show the notification alert but only after the manual refresh, so the logic for showing notifications and stuff is good. I just need some help for writing the Ajax call.
I am pulling the data from a custom template tag so there is no urls for this :
custom_tags.py
@register.simple_tag(name='notification_tag')
def all_notifications():
current = timezone.now() + timezone.timedelta(hours=settings.ADD_HOURS)
notification = Notifications.objects.all().filter(viewed=False, date_to_remind__lte=current)
return notification
@register.simple_tag(name='events')
def all_events():
events = Events.objects.all()
return events
@register.simple_tag(name='current_time')
def now():
current = timezone.now() + timezone.timedelta(hours=settings.ADD_HOURS)
return current
How should I approach this? Where should I put the Ajax code block? Should I write Ajax request inside the custom_tags.py or the views?
I will copy my views.py also, but those functions aren't rendered directly in the topbar. Im using views for another template, which is working properly, and there's no need to go with Ajax there.
views.py
@method_decorator(login_required, name='dispatch')
class AllNotifications(ListView):
model = Notifications
template_name = 'notifications/all.html'
context_object_name = 'notificaion_list'
paginate_by = 5
def get_context_data(self, **kwargs):
context = super(AllNotifications, self).get_context_data(**kwargs)
notifications = self.get_queryset().order_by('date_to_remind')
page = self.request.GET.get('page')
paginator = Paginator(notifications, self.paginate_by)
try:
notifications = paginator.page(page)
except PageNotAnInteger:
notifications = paginator.page(1)
except EmptyPage:
notifications = paginator.page(paginator.num_pages)
context['notification_list'] = notifications
return context
def post(self, request):
if request.is_ajax():
data = {'notifs': self.get_queryset()}
return JsonResponse(data)
@method_decorator(login_required, name='dispatch')
class Notification(DetailView):
model = Notifications
template_name = 'notifications/notification_details.html'
context_object_name = 'notification_details'
def get_context_data(self, **kwargs):
context = super(Notification, self).get_context_data(**kwargs)
self.object.viewed = True
self.object.save()
return context
@method_decorator(login_required, name='dispatch')
class NotificationCreate(CreateView):
model = Notifications
@method_decorator(login_required, name='dispatch')
class NotificationDelete(DeleteView):
model = Notifications
def get_success_url(self):
return reverse('notifications_all')
And this is my base.html :
base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes">
<meta name="description" content="">
<meta name="author" content="dev.Ink">
<link rel="shortcut icon" type="image/png" href="{% static 'login/favicon.ico' %}"/>
<!----------------------------------------------------------------------------------------------------------------->
<title>Teledirekt | {% block title %}{% endblock title %}</title>
<!----------------------------------------------------------------------------------------------------------------->
<!-- Custom fonts for this template-->
<link href="{% static 'dash/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css">
<!-- Page level plugin CSS-->
<link rel="stylesheet" href="{% static 'dash/vendor/datatables/dataTables.bootstrap4.css' %}">
<link rel="stylesheet" href="{% static 'basic/css/style.css' %}">
<!-- Custom styles for this template-->
<link rel="stylesheet" href="{% static 'dash/css/sb-admin-2.css' %}">
<link rel="stylesheet" href="{% static 'base.css' %}">
{# Include Bootstrap 4 and jQuery #}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous">
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: paged-x;
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
scroll-behavior: smooth;
}
</style>
</head>
<!--------------------------------------------------------------------------------------------------------------------->
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Side bar -->
{% include 'sidebar.html' %}
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Top Bar -->
{% include 'topbar.html' %}
<!-- Begin Page Content -->
<div class="container-fluid -align-center">
<!-- Content Row -->
<div class="row">
{% block content_row %}
{% endblock content_row %}
</div>
</div>
</div>
<!-- Footer -->
{% include 'footer.html' %}
<!-- End of Main Content -->
</div>
</div>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Da li želite da izađete?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Klikom na "Izlaz" prekidate Vašu sesiju.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Povratak</button>
<a class="nav-link" href="javascript:{document.getElementById('logout').submit()}" onclick="">Izlaz</a>
<form action="{% url 'user:logout' %}" id="logout" method="POST">
{% csrf_token %}
<input type="hidden">
</form>
</div>
</div>
</div>
</div>
<!-------------------------------------------------------------------------------------------------------------------->
<!-- Bootstrap core JavaScript-->
<script src="{% static 'dash/vendor/jquery/jqueryfull.js' %}"></script>
<script src="{% static 'dash/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Core plugin JavaScript-->
<script src="{% static 'dash/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- Page level plugin JavaScript-->
<script src="{% static 'dash/vendor/chart.js/Chart.min.js' %}"></script>
<script src="{% static 'dash/vendor/datatables/jquery.dataTables.js' %}"></script>
<script src="{% static 'dash/vendor/datatables/dataTables.bootstrap4.js' %}"></script>
<!-- Custom scripts for all pages-->
<script src="{% static 'dash/js/sb-admin-2.min.js' %}"></script>
<script src="{% static 'opportunity/opp.js' %}"></script>
<!-- Demo scripts for this page-->
<script src="{% static 'dash/js/demo/datatables-demo.js' %}"></script>
<script src="{% static 'dash/js/demo/chart-area-demo.js' %}"></script>
</body>
</html>
So one more time, I just need the "badge danger" from span element to appear when the notification time hits the current time, without manual refreshing.