Django 将 HTML table 更新为 AJAX
Django update HTML table with AJAX
好的,我试图理解这里的所有帖子,但我做不到。有些已经过时,有些与我的问题不相似。
别介意我再问
我有一个简单的HTML table,里面有一些数据,我只需要在数据改变时更新数据,而不用刷新它。
对象有'is_locked'字段,我需要做的是,当对象被锁定(is_locked=True)时,会显示一个小储物柜图标。我可以做所有这些,但是在手动刷新之后,这并不好。
因此,当用户锁定对象时,在重定向(页面刷新)后,会显示储物柜图标。但我需要实时,所以当两个用户同时查看同一个 table 时,在对象锁定(来自一个用户)之后,该图标需要出现在另一个用户的浏览器上, 无需刷新页面。
我只需要 'extra' 内容(储物柜图标)在用户锁定对象时实时显示。
尽量忽略自定义名称(它们不是英文的)
我的models.py:
from django.db import models
class OpportunityList(models.Model):
name = models.CharField(max_length=30, blank=True)
address = models.CharField(max_length=100, blank=True)
age = models.IntegerField(blank=True, null=True)
is_locked = models.BooleanField(blank=True, null=True)
...
views.py :
from django.http import JsonResponse
from django.shortcuts import render
from .models import OpportunityList
...
@login_required(login_url='registration/login')
def OptikaList(request):
optika = OpportunityList.objects.all().filter(opp_type='optika')
context = {
'optika': optika
}
if request.is_ajax():
data = {'rendered_table':render_to_string('opportunity/get_more_tables.html', context=context)}
return JsonResponse(data)
return render(request, 'opportunity/opp_optika.html', context)
def updateTable(request):
qs = OpportunityList.objects.all().values()
return JsonResponse({'users': list(qs)})
urls.py :
from django.urls import path
from .views import *
urlpatterns = [
...
path('optika/', OptikaList, name='optika'),
path('ajax/update/', update_table, name='update_table'),
...
opp_optika.html,其中 table 是 ajax 脚本。
{% extends 'base.html' %}
{% load static %}
{% block title %} Optika {% endblock %}
{% block content_row %}
{% if messages %}
{% for message in messages %}
<div class=" container-fluid alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">×</button>
<h4 class="alert-heading">Uspešno!</h4>
<hr>
<p class="mb-0">{{ message }}</p>
</div>
{% endfor %}
{% endif %}
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table table-hover dt-responsive" id="dataTable">
{% include 'opportunity/opp_breadcrumb.html' %}
<h2 style="margin-left: 50%;">OPTIKA</h2>
<thead>
<tr>
<th>Adresa Korisnika</th>
<th>Područje</th>
<th>Korisnik</th>
<th>TIS</th>
<th>Napomena</th>
<th>Akcije</th>
<th style="width: 5px">STATUS</th>
</tr>
</thead>
<tbody>
{% for opp in optika %}
<tr>
<td>{{ opp.optika_korisnik_adr }}</td>
<td>{{ opp.oppc_place }}</td>
<td>{{ opp.optika_korisnik }}</td>
<td>{{ opp.optika_korisnik_tis_id }}</td>
<td>{% if opp.oppc_comment %}{{ opp.oppc_comment }}{% else %}Bez napomene{% endif %}</td>
<td>
<button type="button" class="btn btn-success btn-sm" data-toggle="modal"
data-target="#detalji_modal{{ opp.pk }}">
Detalji
</button>
</td>
<td>
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button class="btn"><i style="width: 50px;color: red" class="fa fa-lock"
aria-hidden="true"></i></button>
</form>
{% endif %}
</td>
</tr>
<!------------------------------------- DETALJIMODAL ---------------------------------------------->
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog"
id="detalji_modal{{ opp.pk }}"
aria-labelledby="detalji_modalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="detalji_modalLabel">Detalji</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="">
<div class="container-fluid">
<h5>{{ opp.optika_korisnik }}</h5>
<p>{{ opp.optika_korisnik_adr.title }}</p>
<p>Broj linije : {{ opp.optika_broj_linije }}</p>
<p>Kontakt : {{ opp.optika_kontakt_tel1 }}</p>
<hr>
<p>Okvirni Datum : {{ opp.optika_instal_okvirni_datum }}</p>
<p>TIS Posla : {{ opp.optika_posao_tis_id }}</p>
<p>Zahtev Info : {{ opp.optika_zahev_uneo }}</p>
<hr>
<p>Datum Unosa : {{ opp.optika_zahtev_datum_unosa }}</p>
<hr>
<p>Napomena : <br> <br>
{% if opp.oppc_comment %} {{ opp.oppc_comment }} {% else %} Nema
napomene za korisnika {{ opp.optika_korisnik|title }}. {% endif %}
</p>
</div>
</div>
<div class="modal-footer">
<p style="margin-right: auto">Zahtev uneo/la : {{ opp.optika_zahev_uneo }}</p>
{% if not opp.is_locked %}
<form action="{% url 'opportunity:poziv' opp.pk %}" method="POST">
{% csrf_token %}
<button type="submit" name="poziv" class="btn btn-outline-danger">
Poziv
</button>
</form>
{% endif %}
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button type="submit" class="btn btn-dark">
<i class="fas fa-lock-open"></i>
Otključaj
</button>
</form>
{% endif %}
<button type="button" class="btn btn-outline-primary" data-dismiss="modal">
Zatvori
</button>
</div>
</div>
</div>
</div>
<!------------------------------------ DETALJI ENDMODAL ------------------------------------------->
{% endfor %}
</tbody>
</table>
</div>
<script>
$(document).ready(function () {
setInterval(function () {
$.ajax({
url: '{% url 'opportunity:optika' %}',
type: "get",
cache: true,
dataType: 'html',
success: function (data) {
console.log("success");
$('#dataTable').html(data.rendered_table);
},
error: function (data) {
alert("Got an error dude " + data);
}
});
}, 5000);
});
</script>
{% endblock content_row %}
get_more_tables.html :
<tr>
<th>Adresa Korisnika</th>
<th>Područje</th>
<th>Korisnik</th>
<th>TIS</th>
<th>Napomena</th>
<th>Akcije</th>
<th style="width: 5px">STATUS</th>
</tr>
{% for opp in optika %}
<tr>
<td>{{ opp.optika_korisnik_adr }}</td>
<td>{{ opp.oppc_place }}</td>
<td>{{ opp.optika_korisnik }}</td>
<td>{{ opp.optika_korisnik_tis_id }}</td>
<td>{% if opp.oppc_comment %}{{ opp.oppc_comment }}{% else %}Bez napomene{% endif %}</td>
<td>
<button type="button" class="btn btn-success btn-sm" data-toggle="modal"
data-target="#detalji_modal{{ opp.pk }}">
Detalji
</button>
</td>
<td>
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button class="btn"><i style="width: 50px;color: red" class="fa fa-lock"
aria-hidden="true"></i></button>
</form>
{% endif %}
</td>
</tr>
<!------------------------------------- DETALJIMODAL ---------------------------------------------->
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog"
id="detalji_modal{{ opp.pk }}"
aria-labelledby="detalji_modalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="detalji_modalLabel">Detalji</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="">
<div class="container-fluid">
<h5>{{ opp.optika_korisnik }}</h5>
<p>{{ opp.optika_korisnik_adr.title }}</p>
<p>Broj linije : {{ opp.optika_broj_linije }}</p>
<p>Kontakt : {{ opp.optika_kontakt_tel1 }}</p>
<hr>
<p>Okvirni Datum : {{ opp.optika_instal_okvirni_datum }}</p>
<p>TIS Posla : {{ opp.optika_posao_tis_id }}</p>
<p>Zahtev Info : {{ opp.optika_zahev_uneo }}</p>
<hr>
<p>Datum Unosa : {{ opp.optika_zahtev_datum_unosa }}</p>
<hr>
<p>Napomena : <br> <br>
{% if opp.oppc_comment %} {{ opp.oppc_comment }} {% else %} Nema
napomene za korisnika {{ opp.optika_korisnik|title }}. {% endif %}
</p>
</div>
</div>
<div class="modal-footer">
<p style="margin-right: auto">Zahtev uneo/la : {{ opp.optika_zahev_uneo }}</p>
{% if not opp.is_locked %}
<form action="{% url 'opportunity:poziv' opp.pk %}" method="POST">
{% csrf_token %}
<button type="submit" name="poziv" class="btn btn-outline-danger">
Poziv
</button>
</form>
{% endif %}
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button type="submit" class="btn btn-dark">
<i class="fas fa-lock-open"></i>
Otključaj
</button>
</form>
{% endif %}
<button type="button" class="btn btn-outline-primary" data-dismiss="modal">
Zatvori
</button>
</div>
</div>
</div>
</div>
<!------------------------------------ DETALJI ENDMODAL ------------------------------------------->
{% endfor %}
您的代码中有很多问题。
您当前的 AJAX 调用的作用:调用您的 displayUser
视图。此视图呈现整个 crud.html
模板(包括 javascript!)并 return 对其进行处理。您的 javascript 将它放在您定义的位置。所以在第一个 AJAX 调用之后,你得到了一些嵌套的 table 结构,其中有两个 javascript 块,两个 运行 是并行的。
然后这两个函数开始再次调用视图以接收完全呈现的页面。因此,一段时间后,您会得到一个包含多个并行脚本 运行 的混乱网页,将完全渲染的页面放在各处。这肯定会占用内存。
你可以做的是检查你的 request
是否是一个 ajax 请求,在这种情况下,只将内部 table 和 return 渲染回你的 javascript:
def displayUser(request):
users = CrudUser.objects.all()
context = {
'users': users
}
if request.is_ajax():
data = {'rendered_table': render_to_string('table_contents.html', context=context)}
return JsonResponse(data)
return render(request, 'crud.html', context)
内部子模板table:
# table_contents.html
<tr>
<th>Name</th>
<th>Address</th>
<th>Age</th>
</tr>
{% for user in users %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.address }}</td>
<td>{{ user.age }}</td>
</tr>
{% endfor %}
现在您可以将其放入 javascript
的模板中
$('#_appendHere').html(data.rendered_table);
最后一点:在你的 ajax 函数中,我认为它应该是 data_type
而不是 dataType
。
好的,我试图理解这里的所有帖子,但我做不到。有些已经过时,有些与我的问题不相似。
别介意我再问
我有一个简单的HTML table,里面有一些数据,我只需要在数据改变时更新数据,而不用刷新它。
对象有'is_locked'字段,我需要做的是,当对象被锁定(is_locked=True)时,会显示一个小储物柜图标。我可以做所有这些,但是在手动刷新之后,这并不好。
因此,当用户锁定对象时,在重定向(页面刷新)后,会显示储物柜图标。但我需要实时,所以当两个用户同时查看同一个 table 时,在对象锁定(来自一个用户)之后,该图标需要出现在另一个用户的浏览器上, 无需刷新页面。
我只需要 'extra' 内容(储物柜图标)在用户锁定对象时实时显示。
尽量忽略自定义名称(它们不是英文的)
我的models.py:
from django.db import models
class OpportunityList(models.Model):
name = models.CharField(max_length=30, blank=True)
address = models.CharField(max_length=100, blank=True)
age = models.IntegerField(blank=True, null=True)
is_locked = models.BooleanField(blank=True, null=True)
...
views.py :
from django.http import JsonResponse
from django.shortcuts import render
from .models import OpportunityList
...
@login_required(login_url='registration/login')
def OptikaList(request):
optika = OpportunityList.objects.all().filter(opp_type='optika')
context = {
'optika': optika
}
if request.is_ajax():
data = {'rendered_table':render_to_string('opportunity/get_more_tables.html', context=context)}
return JsonResponse(data)
return render(request, 'opportunity/opp_optika.html', context)
def updateTable(request):
qs = OpportunityList.objects.all().values()
return JsonResponse({'users': list(qs)})
urls.py :
from django.urls import path
from .views import *
urlpatterns = [
...
path('optika/', OptikaList, name='optika'),
path('ajax/update/', update_table, name='update_table'),
...
opp_optika.html,其中 table 是 ajax 脚本。
{% extends 'base.html' %}
{% load static %}
{% block title %} Optika {% endblock %}
{% block content_row %}
{% if messages %}
{% for message in messages %}
<div class=" container-fluid alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">×</button>
<h4 class="alert-heading">Uspešno!</h4>
<hr>
<p class="mb-0">{{ message }}</p>
</div>
{% endfor %}
{% endif %}
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table table-hover dt-responsive" id="dataTable">
{% include 'opportunity/opp_breadcrumb.html' %}
<h2 style="margin-left: 50%;">OPTIKA</h2>
<thead>
<tr>
<th>Adresa Korisnika</th>
<th>Područje</th>
<th>Korisnik</th>
<th>TIS</th>
<th>Napomena</th>
<th>Akcije</th>
<th style="width: 5px">STATUS</th>
</tr>
</thead>
<tbody>
{% for opp in optika %}
<tr>
<td>{{ opp.optika_korisnik_adr }}</td>
<td>{{ opp.oppc_place }}</td>
<td>{{ opp.optika_korisnik }}</td>
<td>{{ opp.optika_korisnik_tis_id }}</td>
<td>{% if opp.oppc_comment %}{{ opp.oppc_comment }}{% else %}Bez napomene{% endif %}</td>
<td>
<button type="button" class="btn btn-success btn-sm" data-toggle="modal"
data-target="#detalji_modal{{ opp.pk }}">
Detalji
</button>
</td>
<td>
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button class="btn"><i style="width: 50px;color: red" class="fa fa-lock"
aria-hidden="true"></i></button>
</form>
{% endif %}
</td>
</tr>
<!------------------------------------- DETALJIMODAL ---------------------------------------------->
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog"
id="detalji_modal{{ opp.pk }}"
aria-labelledby="detalji_modalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="detalji_modalLabel">Detalji</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="">
<div class="container-fluid">
<h5>{{ opp.optika_korisnik }}</h5>
<p>{{ opp.optika_korisnik_adr.title }}</p>
<p>Broj linije : {{ opp.optika_broj_linije }}</p>
<p>Kontakt : {{ opp.optika_kontakt_tel1 }}</p>
<hr>
<p>Okvirni Datum : {{ opp.optika_instal_okvirni_datum }}</p>
<p>TIS Posla : {{ opp.optika_posao_tis_id }}</p>
<p>Zahtev Info : {{ opp.optika_zahev_uneo }}</p>
<hr>
<p>Datum Unosa : {{ opp.optika_zahtev_datum_unosa }}</p>
<hr>
<p>Napomena : <br> <br>
{% if opp.oppc_comment %} {{ opp.oppc_comment }} {% else %} Nema
napomene za korisnika {{ opp.optika_korisnik|title }}. {% endif %}
</p>
</div>
</div>
<div class="modal-footer">
<p style="margin-right: auto">Zahtev uneo/la : {{ opp.optika_zahev_uneo }}</p>
{% if not opp.is_locked %}
<form action="{% url 'opportunity:poziv' opp.pk %}" method="POST">
{% csrf_token %}
<button type="submit" name="poziv" class="btn btn-outline-danger">
Poziv
</button>
</form>
{% endif %}
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button type="submit" class="btn btn-dark">
<i class="fas fa-lock-open"></i>
Otključaj
</button>
</form>
{% endif %}
<button type="button" class="btn btn-outline-primary" data-dismiss="modal">
Zatvori
</button>
</div>
</div>
</div>
</div>
<!------------------------------------ DETALJI ENDMODAL ------------------------------------------->
{% endfor %}
</tbody>
</table>
</div>
<script>
$(document).ready(function () {
setInterval(function () {
$.ajax({
url: '{% url 'opportunity:optika' %}',
type: "get",
cache: true,
dataType: 'html',
success: function (data) {
console.log("success");
$('#dataTable').html(data.rendered_table);
},
error: function (data) {
alert("Got an error dude " + data);
}
});
}, 5000);
});
</script>
{% endblock content_row %}
get_more_tables.html :
<tr>
<th>Adresa Korisnika</th>
<th>Područje</th>
<th>Korisnik</th>
<th>TIS</th>
<th>Napomena</th>
<th>Akcije</th>
<th style="width: 5px">STATUS</th>
</tr>
{% for opp in optika %}
<tr>
<td>{{ opp.optika_korisnik_adr }}</td>
<td>{{ opp.oppc_place }}</td>
<td>{{ opp.optika_korisnik }}</td>
<td>{{ opp.optika_korisnik_tis_id }}</td>
<td>{% if opp.oppc_comment %}{{ opp.oppc_comment }}{% else %}Bez napomene{% endif %}</td>
<td>
<button type="button" class="btn btn-success btn-sm" data-toggle="modal"
data-target="#detalji_modal{{ opp.pk }}">
Detalji
</button>
</td>
<td>
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button class="btn"><i style="width: 50px;color: red" class="fa fa-lock"
aria-hidden="true"></i></button>
</form>
{% endif %}
</td>
</tr>
<!------------------------------------- DETALJIMODAL ---------------------------------------------->
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog"
id="detalji_modal{{ opp.pk }}"
aria-labelledby="detalji_modalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="detalji_modalLabel">Detalji</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="">
<div class="container-fluid">
<h5>{{ opp.optika_korisnik }}</h5>
<p>{{ opp.optika_korisnik_adr.title }}</p>
<p>Broj linije : {{ opp.optika_broj_linije }}</p>
<p>Kontakt : {{ opp.optika_kontakt_tel1 }}</p>
<hr>
<p>Okvirni Datum : {{ opp.optika_instal_okvirni_datum }}</p>
<p>TIS Posla : {{ opp.optika_posao_tis_id }}</p>
<p>Zahtev Info : {{ opp.optika_zahev_uneo }}</p>
<hr>
<p>Datum Unosa : {{ opp.optika_zahtev_datum_unosa }}</p>
<hr>
<p>Napomena : <br> <br>
{% if opp.oppc_comment %} {{ opp.oppc_comment }} {% else %} Nema
napomene za korisnika {{ opp.optika_korisnik|title }}. {% endif %}
</p>
</div>
</div>
<div class="modal-footer">
<p style="margin-right: auto">Zahtev uneo/la : {{ opp.optika_zahev_uneo }}</p>
{% if not opp.is_locked %}
<form action="{% url 'opportunity:poziv' opp.pk %}" method="POST">
{% csrf_token %}
<button type="submit" name="poziv" class="btn btn-outline-danger">
Poziv
</button>
</form>
{% endif %}
{% if opp.is_locked %}
<form action="{% url 'opportunity:delete_locked' opp.pk %}" method="POST"
style="display: table-cell">
{% csrf_token %}
<button type="submit" class="btn btn-dark">
<i class="fas fa-lock-open"></i>
Otključaj
</button>
</form>
{% endif %}
<button type="button" class="btn btn-outline-primary" data-dismiss="modal">
Zatvori
</button>
</div>
</div>
</div>
</div>
<!------------------------------------ DETALJI ENDMODAL ------------------------------------------->
{% endfor %}
您的代码中有很多问题。
您当前的 AJAX 调用的作用:调用您的 displayUser
视图。此视图呈现整个 crud.html
模板(包括 javascript!)并 return 对其进行处理。您的 javascript 将它放在您定义的位置。所以在第一个 AJAX 调用之后,你得到了一些嵌套的 table 结构,其中有两个 javascript 块,两个 运行 是并行的。
然后这两个函数开始再次调用视图以接收完全呈现的页面。因此,一段时间后,您会得到一个包含多个并行脚本 运行 的混乱网页,将完全渲染的页面放在各处。这肯定会占用内存。
你可以做的是检查你的 request
是否是一个 ajax 请求,在这种情况下,只将内部 table 和 return 渲染回你的 javascript:
def displayUser(request):
users = CrudUser.objects.all()
context = {
'users': users
}
if request.is_ajax():
data = {'rendered_table': render_to_string('table_contents.html', context=context)}
return JsonResponse(data)
return render(request, 'crud.html', context)
内部子模板table:
# table_contents.html
<tr>
<th>Name</th>
<th>Address</th>
<th>Age</th>
</tr>
{% for user in users %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.address }}</td>
<td>{{ user.age }}</td>
</tr>
{% endfor %}
现在您可以将其放入 javascript
的模板中$('#_appendHere').html(data.rendered_table);
最后一点:在你的 ajax 函数中,我认为它应该是 data_type
而不是 dataType
。