백엔드 개발 파이썬 튜토리얼 使用Node.js和Socket.IO扩展Django的实时处理功能

使用Node.js和Socket.IO扩展Django的实时处理功能

Jun 06, 2016 am 11:25 AM
python

 今天,我们的目标是使用Django,Redis,和Socket.IO建立一个实时的聊天室。虽然几乎所有的Web应用程序都可以建立一个聊天室的。这篇文章将以较高的水平告诉你如何将基于REST的应用程序转换成一个实时的Web应用程序的。我会使用Django创建REST的部分,实际上自由地使用任何你舒服的语言/框架均可。接下来,让我们跳进代码,先列举我们所需要的部分。

组成:

  •     Django 1.4+
  •     Redis 2.6.x (版本可选,但是建议使用)
  •     Redis-py 2.7.x (仅当你使用Redis时需要)
  •     Node.js v0.8.x
  •     Socket.IO v0.9.x
  •     Cookie v0.0.5
  •     数据库、sqlite、其他你觉得类似数据库形式的 均可


 

你的使用的版本可能与我不同,我暂时未测试其他版本,全部使用当前最新稳定版本。如果你无法通过下面方法安装,我已经编译好Ubuntu的软件包。你可以从评论中得到其他操作系统版本情况。
 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#https://docs.djangoproject.com/en/dev/topics/install/

sudo apt-get install python-pip

sudo pip install django

  

#http://redis.io/download

sudo apt-get install redis-server

  

#https://github.com/andymccurdy/redis-py

sudo pip install redis 

    

#https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager

sudo apt-get install python-software-properties

sudo add-apt-repository ppa:chris-lea/node.js

sudo apt-get update

sudo apt-get install nodejs

  

#https://github.com/LearnBoost/socket.io

npm install socket.io

  

#https://github.com/shtylman/node-cookie

npm install cookie

로그인 후 복사

让我们从Django Project开始

1

2

3

django-admin.py startproject realtime_tutorial && cd realtime_tutorial

python manage.py startapp core

mkdir nodejs

로그인 후 복사

执行完以上的代码,django project就配置好了,接下来要做的是在settings文件中设置数据库。先创建一个空白数据库。(这是一个settings file的例子。在我的app中添加了一个“core”然后配置templates和urls的路径。你可以随意更改settings中的配置信息,但是要与你的app相对应。

Model

models很简单,我们将要建一个包含user和text的表。如果你想让他更复杂一些,可以添加chatroom等信息。(为了简单起见,这里只写了两个)

1

2

3

4

5

6

from django.db import models

from django.contrib.auth.models import User

  

class Comments(models.Model):

  user = models.ForeignKey(User)

  text = models.CharField(max_length=255)

로그인 후 복사

这就是我们将要使用的model,接下来执行下面的syncdb代码(第一行代码),创建数据库。然后创建几个user来测试。(第二行代码)

1

2

3

4

python manage.py syncdb

python manage.py createsuperuser

  

Node Server With Socket.IO

로그인 후 복사

这一部分将要介绍实时信息的发送和获取。使用Node.js创建一个依赖Socket.IO的app server,使用Redis 来做这项苦差事。在nodejs字典中,创建一个叫做“chat.js”的文件,然后把它放在这里:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

var http = require('http');

var server = http.createServer().listen(4000);

var io = require('socket.io').listen(server);

var cookie_reader = require('cookie');

var querystring = require('querystring');

  

var redis = require('socket.io/node_modules/redis');

var sub = redis.createClient();

 

  

//订阅chat channel

 

 

sub.subscribe('chat');

 

  

//配置socket.io来存储Django设置的cookie

io.configure(function(){

  io.set('authorization', function(data, accept){

    if(data.headers.cookie){

      data.cookie = cookie_reader.parse(data.headers.cookie);

      return accept(null, true);

    }

    return accept('error', false);

  });

  io.set('log level', 1);

});

  

io.sockets.on('connection', function (socket) {

    

  //把信息从Redis发送到客户端

  sub.on('message', function(channel, message){

    socket.send(message);

  });

    

  //客户端通过socket.io发送消息

  socket.on('send_message', function (message) {

    values = querystring.stringify({

      comment: message,

      sessionid: socket.handshake.cookie['sessionid'],

    });

      

    var options = {

      host: 'localhost',

      port: 3000,

      path: '/node_api',

      method: 'POST',

      headers: {

        'Content-Type': 'application/x-www-form-urlencoded',

        'Content-Length': values.length

      }

    };

      

    //使用Django server发消息

    var req = http.get(options, function(res){

      res.setEncoding('utf8');

        

      //输出错误信息

      res.on('data', function(message){

        if(message != 'Everything worked :)'){

          console.log('Message: ' + message);

        }

      });

    });

      

    req.write(values);

    req.end();

  });

});

로그인 후 복사

首先,我们导入并创建http server来监听localhost 4000端口。然后订阅Redis的 "chat" chanel。最后,只要我们在Django view中调用就可以了。


上次我们设置了Socket.IO能在本地领域使用cookie的那个Django设置,这能让我们通过socket.handshake.cookie去访问cookie数据。能让我们怎样得到用户的session会话。

我们设置Socket.IO的cookies之后我们才能持有很多事件,第一个事件是Redis 发布通道,当我们的用户注意到一个新的消息已经被通知它将发送消息给所有站点的客户端。

另一个事件是当客户端通过Socket.IO发送一个信息,我们使用字符串查询(queryString)模块去创建一个query查询才能被发送到我们的Django服务。我们的Django服务在本地端口3000将会运行但你能改变了那个需求。路径设置成/node_api那个URL我们将不久创建在Django旁边。一旦我们发送queryString我们等待的Django就会保存相关组件并给我们返回"Everything worked(都在工作)"。如果我们没有得到返回给我们的输出错误就关闭节点控制台


一个关于不使用Redis的节点

你真的完全没必要为这项目使用Redis,我发现它将是一个好的学习体验,如果你想分流Redis你可以创建一个通道,使用表达式或一些其它类库,在这上面的代码会从Django里接收一个消息当一个注释被保存时,然后你能通过Socket.IO添加注释给所有的客户端
模板

这就是我们所有HTML和javascript被放置的地方,它允许我们显示注释和交互我们的Node服务

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

<!DOCTYPE html>

<html>

<head>

 <title>Realtime Django</title>

 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" type="text/javascript"></script>

 <script src="http://localhost:4000/socket.io/socket.io.js"></script>

 <script>

  $(document).ready(function(){

   var socket = io.connect('localhost', {port: 4000});

     

   socket.on('connect', function(){

    console.log("connect");

   });

     

   var entry_el = $('#comment');

         

   socket.on('message', function(message) {

    //Escape HTML characters

    var data = message.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");

      

    //Append message to the bottom of the list

    $('#comments').append('<li>' + data + '</li>');

    window.scrollBy(0, 10000000000);

    entry_el.focus();

   });

            

   entry_el.keypress(function(event){

    //When enter is pressed send input value to node server

    if(event.keyCode != 13) return;

    var msg = entry_el.attr('value');

    if(msg){

      socket.emit('send_message', msg, function(data){

        console.log(data);

      });

      

    //Clear input value

    entry_el.attr('value', '');

    }

   });

  });

 </script>

</head>

<body>

  <ul id="comments">

    {% for comment in comments %}

      <li>{{comment.user}}: {{comment.text}}</li>

    {% endfor %}

  </ul>

  <input type="text" id="comment" name="comment" />

</body>

</html>

로그인 후 복사


在上面我们用socket.IO在本地端口4000连接我们的节点服务。当从服务器得到了一个信息我们就在目录和添加它到我们注释列表里做了些转义,当我们想要发送一个信息我们就对输入盒子里做了相应的13(按下一个键)的按键检查。一旦那被按下后我们就发出信息给服务器使其被持有。一旦它被Django保存到我们的数据库我们就得到一个"message"事件将其添加到我们的会话列表里

我们的Django显示我们在下一步将加载一个"comments"变量,因此我们那样设置并遍历下面所有的循环。这部分仅仅是当页面初始加载时使用了,我们的javascript将添加数据给这个目录作为一个新的数据来自我们的Node服务

View

打开realtime_tutorial/core/views.py,然后像我一样编辑:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

from core.models import Comments, User

  

from django.shortcuts import render

from django.http import HttpResponse, HttpResponseServerError

from django.views.decorators.csrf import csrf_exempt

from django.contrib.sessions.models import Session

from django.contrib.auth.decorators import login_required

  

import redis

  

@login_required

def home(request):

  comments = Comments.objects.select_related().all()[0:100]

  return render(request, 'index.html', locals())

  

@csrf_exempt

def node_api(request):

  try:

    #通过sessionid获得 user

    session = Session.objects.get(session_key=request.POST.get('sessionid'))

    user_id = session.get_decoded().get('_auth_user_id')

    user = User.objects.get(id=user_id)

  

    #创建Comment

    Comments.objects.create(user=user, text=request.POST.get('comment'))

      

    #创建后就把它发送到聊天室

    r = redis.StrictRedis(host='localhost', port=6379, db=0)

    r.publish('chat', user.username + ': ' + request.POST.get('comment'))

      

    return HttpResponse("Everything worked :)")

  except Exception, e:

    return HttpResponseServerError(str(e))

로그인 후 복사

让我们看看这里发生了什么。home是一个标准的view文件。使用select_related来获得每一个comment的username,而不是在页面第一次加载的时候,就返回一个comment的query集合。

第二个就是我们Node app发送信息的view。我们从POST中获取sessionid,然后通过解码获得userid。确定user存在后,就可以创建comment了。现在吧username 和 comment 发送到 Redis server。最后,把数据发送到这里叫做"chat"的频道。

URLs

这里比较简单,因为我们将要使用Django自带的views和template。

1

2

3

4

5

6

7

8

from django.conf.urls import patterns, include, url

  

urlpatterns = patterns('',

  url(r'^$', 'core.views.home', name='home'),

  url(r'^node_api$', 'core.views.node_api', name='node_api'),

  url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'admin/login.html'}, name='login'),

  url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}, name='logout'),

)

로그인 후 복사

Start It Up!

打开servers。

1

2

3

4

python manage.py runserver localhost:3000

  

#In a new terminal tab cd into the nodejs directory we created earlier

node chat.js

로그인 후 복사

我把代码放到github。如果你想把它做得更好,就允许user创建、加入聊天室。你也可以使用PHP或者Rails开发。

如果你有什么问题,请在评论处写下或联系我。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

XML을 PDF로 변환 할 수있는 모바일 앱이 있습니까? XML을 PDF로 변환 할 수있는 모바일 앱이 있습니까? Apr 02, 2025 pm 08:54 PM

XML을 PDF로 직접 변환하는 응용 프로그램은 근본적으로 다른 두 형식이므로 찾을 수 없습니다. XML은 데이터를 저장하는 데 사용되는 반면 PDF는 문서를 표시하는 데 사용됩니다. 변환을 완료하려면 Python 및 ReportLab과 같은 프로그래밍 언어 및 라이브러리를 사용하여 XML 데이터를 구문 분석하고 PDF 문서를 생성 할 수 있습니다.

휴대폰에서 XML을 PDF로 변환 할 때 변환 속도가 빠르나요? 휴대폰에서 XML을 PDF로 변환 할 때 변환 속도가 빠르나요? Apr 02, 2025 pm 10:09 PM

모바일 XML에서 PDF의 속도는 다음 요인에 따라 다릅니다. XML 구조의 복잡성. 모바일 하드웨어 구성 변환 방법 (라이브러리, 알고리즘) 코드 품질 최적화 방법 (효율적인 라이브러리 선택, 알고리즘 최적화, 캐시 데이터 및 다중 스레딩 사용). 전반적으로 절대적인 답변은 없으며 특정 상황에 따라 최적화해야합니다.

휴대 전화에서 XML 파일을 PDF로 변환하는 방법은 무엇입니까? 휴대 전화에서 XML 파일을 PDF로 변환하는 방법은 무엇입니까? Apr 02, 2025 pm 10:12 PM

단일 애플리케이션으로 휴대 전화에서 직접 XML에서 PDF 변환을 완료하는 것은 불가능합니다. 두 단계를 통해 달성 할 수있는 클라우드 서비스를 사용해야합니다. 1. 클라우드에서 XML을 PDF로 변환하십시오. 2. 휴대 전화에서 변환 된 PDF 파일에 액세스하거나 다운로드하십시오.

이미지로 변환 된 XML의 크기를 제어하는 ​​방법은 무엇입니까? 이미지로 변환 된 XML의 크기를 제어하는 ​​방법은 무엇입니까? Apr 02, 2025 pm 07:24 PM

XML을 통해 이미지를 생성하려면 XML에서 메타 데이터 (크기, 색상)를 기반으로 이미지를 생성하기 위해 브리지로 그래프 라이브러리 (예 : Pillow 및 JFreeChart)를 사용해야합니다. 이미지의 크기를 제어하는 ​​열쇠는 & lt; width & gt의 값을 조정하는 것입니다. 및 & lt; 높이 & gt; XML의 태그. 그러나 실제 애플리케이션에서 XML 구조의 복잡성, 그래프 드로잉의 편향, 이미지 생성 속도 및 메모리 소비 및 이미지 형식 선택은 모두 생성 된 이미지 크기에 영향을 미칩니다. 따라서 그래픽 라이브러리에 능숙한 XML 구조에 대한 깊은 이해가 필요하고 최적화 알고리즘 및 이미지 형식 선택과 같은 요소를 고려해야합니다.

권장 XML 서식 도구 권장 XML 서식 도구 Apr 02, 2025 pm 09:03 PM

XML 서식 도구는 규칙에 따라 코드를 입력하여 가독성과 이해를 향상시킬 수 있습니다. 도구를 선택할 때는 사용자 정의 기능, 특수 상황 처리, 성능 및 사용 편의성에주의하십시오. 일반적으로 사용되는 도구 유형에는 온라인 도구, IDE 플러그인 및 명령 줄 도구가 포함됩니다.

C 언어 합계의 기능은 무엇입니까? C 언어 합계의 기능은 무엇입니까? Apr 03, 2025 pm 02:21 PM

C 언어에는 내장 합계 기능이 없으므로 직접 작성해야합니다. 합계는 배열 및 축적 요소를 가로 질러 달성 할 수 있습니다. 루프 버전 : 루프 및 배열 길이를 사용하여 계산됩니다. 포인터 버전 : 포인터를 사용하여 배열 요소를 가리키며 효율적인 합계는 자체 증가 포인터를 통해 달성됩니다. 동적으로 배열 버전을 할당 : 배열을 동적으로 할당하고 메모리를 직접 관리하여 메모리 누출을 방지하기 위해 할당 된 메모리가 해제되도록합니다.

XML 형식을 여는 방법 XML 형식을 여는 방법 Apr 02, 2025 pm 09:00 PM

대부분의 텍스트 편집기를 사용하여 XML 파일을여십시오. 보다 직관적 인 트리 디스플레이가 필요한 경우 Oxygen XML 편집기 또는 XMLSPy와 같은 XML 편집기를 사용할 수 있습니다. 프로그램에서 XML 데이터를 처리하는 경우 프로그래밍 언어 (예 : Python) 및 XML 라이브러 (예 : XML.etree.elementtree)를 사용하여 구문 분석해야합니다.

XML을 PDF로 변환 할 수있는 모바일 앱이 있습니까? XML을 PDF로 변환 할 수있는 모바일 앱이 있습니까? Apr 02, 2025 pm 09:45 PM

XML 구조가 유연하고 다양하기 때문에 모든 XML 파일을 PDF로 변환 할 수있는 앱은 없습니다. XML에서 PDF의 핵심은 데이터 구조를 페이지 레이아웃으로 변환하는 것입니다. XML을 구문 분석하고 PDF를 생성해야합니다. 일반적인 방법으로는 요소 트리와 같은 파이썬 라이브러리를 사용한 XML 및 ReportLab 라이브러리를 사용하여 PDF를 생성하는 XML을 구문 분석합니다. 복잡한 XML의 경우 XSLT 변환 구조를 사용해야 할 수도 있습니다. 성능을 최적화 할 때는 멀티 스레드 또는 멀티 프로세스 사용을 고려하고 적절한 라이브러리를 선택하십시오.

See all articles