如何使用 AJAX 或类似的东西在 Django 中使用 Python 脚本?

Posted

技术标签:

【中文标题】如何使用 AJAX 或类似的东西在 Django 中使用 Python 脚本?【英文标题】:How to use Python script in Django using AJAX or something like that? 【发布时间】:2018-09-25 05:12:00 【问题描述】:

我正在开发一个物联网项目,例如学校和大学的智能考勤和无现金支付系统。我使用 Raspberry Pi 3 作为我的客户端机器和 DigitalOcean 来托管 PostgreSQL 和核心 Django 项目。除了 Raspberry Pi,我还在使用 EM-18 RFID 阅读器和 R305 指纹阅读器。现在,到现在为止,我已经构建了一个 CLI 实用程序来使用项目,但对于一个不熟悉 Linux 或一般 shell 的人来说,它并不是很方便。

现在我的问题在于我当前的代码逻辑。例如,如果我想将学生信息连同他们的 RFID/指纹信息一起添加到数据库中,我首先扫描分配给他们的 RFID 标签。检查该标签是否已经在数据库中,如果没有,则询问他们的信息。在这一步之后,我再次要求他们再次点击同一张卡以注册他们的指纹。所有这些过程都可以在 CLI 上正常工作。我无法弄清楚如何让操作员知道现在要执行哪个步骤。虽然我在 Django 中构建了一个 Web 界面,但它既不友好也不交互。我想我必须使用 JSON/AJAX 来做到这一点,但我不知道该怎么做。

【问题讨论】:

【参考方案1】:

我终于明白了。我已将过程分为多个部分。然后我调用 AJAX 来访问它。

我的urls.py 文件:

from django.conf.urls import url
from .views import tag, check_tagid, scan_tag

urlpatterns = [
    url(r'^tag/', tag, name="tag"),
    url(r'^check_tagid/', check_tagid, name="check_tagid"),
    url(r'^scan_tag/', scan_tag, name="scan_tag"),
]

我的views.py 文件:

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from .models import Student
import serial

def check_tagid(request):
    """Check if scanned tag id is already associated or not"""
    tagid = request.GET.get('tagid', None)
    if Student.objects.filter(tag_id__iexact=tagid).exists():
        data = 
            'is_taken': Student.objects.filter(tag_id__iexact=tagid).exists(),
            'student': Student.objects.get(tag_id=tagid).name
        
    else:
        data = 
            'is_taken': Student.objects.filter(tag_id__iexact=tagid).exists(),
        
    return JsonResponse(data)


def scan_tag(request):
    """Function to check if tag is scanned or not"""
    if request.is_ajax():
        ## Init RFID reader
        data = serial.Serial(
                            port='/dev/ttyUSB1',
                            baudrate = 9600,
                            parity=serial.PARITY_NONE,
                            stopbits=serial.STOPBITS_ONE,
                            bytesize=serial.EIGHTBITS
                            )

        context = 'tagid': data.read(12).decode("utf-8")
        return JsonResponse(context) 
    else:
        return HttpResponse("This route only handles AJAX requests")


def tag(request):
    return render(request, 'students/tag.html', )

我的tag.html 文件:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
</head>
<body>
    <center><h1><div id="tag_id">Scanning for tag</div></h1></center>
    <div id="if_exists"></div>


  <script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>

<script type="text/javascript">
$(document).ready(function() 
    $.get("/scan_tag/", function(data) 
        console.log(data.tagid);
        var x = document.createElement("INPUT");
        x.setAttribute("id", "tag_id_in");
        x.setAttribute("type", "hidden");
        x.setAttribute("value", data.tagid);
        document.body.appendChild(x);
        // check tag
        tagid = $("#tag_id_in").val();
        console.log(tagid);
        $.ajax(
            type: "GET",
            url: "% url 'check_tagid' %",
            data: 
                'tagid': tagid
            ,
            success: function(data) 
                if (data.is_taken) 
                    document.getElementById('tag_id').innerHTML = "Welcome "+data.student;
                 else 
                    document.getElementById('tag_id').innerHTML = "No student with this tag id found";
                
            
        );
    );
);
</script>


</body>
</html>

所有这些现在都按预期工作。

所以,/tag/ 是主要入口点。现在在tag.html 中,我在/scan_tag/ 上使用jQuery get 方法。它将返回 RFID 标签号。然后我在/check_tagid/ 上调用 AJAX,它的真/假取决于学生是否在数据库中。

【讨论】:

对不起,我完全忘记了这个问题,很高兴你能自己解决。并使用“filter.exsist()”而不是“get()”来避免“尝试/期望”。如果您正在寻找进一步的改进:“data = serial.Serial(...”似乎是错误的,因为您每次调用函数时都会对其进行初始化。这应该是全局 IMO。您还可以将 jQuery ajax 调用转换为 nativ XM​​LRequest 到摆脱 jQuery 开销。 @hansTheFranz 非常感谢您的回复!我尝试将“data = serial.Serial(...”设置为全局,但似乎没有扫描 RFID 标签。此外,我猜将其设置为非全局会节省电力,因为它需要 12V。我对此一无所知原生 XMLRequest。你能给我推荐一个很好的参考吗?我找到了this 再次感谢你的建议!【参考方案2】:

请不要将其视为答案,而更像是更长的评论;)

所以首先阅读 MVC 概念(例如:https://djangobook.com/model-view-controller-design-pattern/)以了解 Web 界面如何与其余代码交互。

经典的 django 方式是

    根据您的model 创建一个form(在forms.py 中)。 你会写一些 html 来在网站上显示表单 验证views.py中的表单输入 发回结果并显示它们(同样是 html)

如果您想使用 AJAX 进行此操作,则需要做一些额外的工作,但结果是值得的。 (例如:How to POST a django form with AJAX & jQuery)

您将调用您首先在urls.py 文件中初始化的特定网址(在 django 2.0 中为path('checkForm', views.checkForm, name='checkForm'),

url 指向在views.py 中定义的函数,名称为checkForm(与本示例中的url 路径相同,但您可以随意调用它)。在这个函数中,您可以编写您的 python 代码或从那里调用函数来执行您的数据库查询、验证等。 发回带有代码结果的响应。

success: function(data, status) $('#whatever').html(data); alert("whatever");

“data”在这里是来自服务器的响应。 我希望我给了你一个正确方向的提示。请问您是否卡在某个地方。

附言我不知道如何通过 http 发送指纹数据,检查是否有一些库。

x=data.read(12).decode("utf-8")
tag_id_in = x

这是不好的代码,请去掉 x。第一个 x 是一个错误的变量名,第二个是完全多余的。 您还希望将您的 print 语句转换为 logs 或其他任何内容,但打印不会让您走得太远。

【讨论】:

这真的很有帮助,我已经按照你的建议更新了我的代码。看我的views.py here。现在我得到了 RFID 标签数据,它也被提交到数据库,但我的问题是我没有得到HttpResponse("Form submitted")。它只是重新开始阅读标签。我希望它只是一次性的过程。另外,建议更好的代码实践来消除“try except block”。提交表单后,我不知道为什么必须扫描我的标签才能提交数据并显示 HttpResponse。

以上是关于如何使用 AJAX 或类似的东西在 Django 中使用 Python 脚本?的主要内容,如果未能解决你的问题,请参考以下文章

Django - 如何使用 JQuery Ajax 插入多个表单数据

Django Channels 2.x 还是 Ajax?

Django Infinite Scroll 没有运行 Ajax 的东西

Django 中的 Ajax 侧边栏

django-python如何将文本转换为pdf

如何在ajax中使用django url?