Node. js and Socket. IO extend Django's real-time processing functions

Source: Internet
Author: User
Tags set socket django server install django node server pip install django redis server

Node. js and Socket. IO extend Django's real-time processing functions

This article mainly introduces the use of Node. js and Socket. i/O extends Django's real-time processing function. The real-time asynchronous processing function is quite powerful. The example given in this article is to create a real-time chat room. For more information, see

Today, our goal is to use Django, Redis, and Socket. IO to create a real-time chat room. Although almost all Web applications can create a chat room. This article tells you how to convert a REST-based application into a real-time Web application at a high level. I will use Django to create the REST part. In fact, it is free to use any comfortable language/framework. Next, let's jump into the code and list what we need first.

Composition:

Django 1.4 +

Redis 2.6.x (optional, but recommended)

Redis-py 2.7.x (only required when you use Redis)

Node. js v0.8.x

Socket. IO v0.9.x

Cookie v0.0.5

Databases, sqlite, and others that you think are similar to databases

Your version may be different from mine. I have not tested other versions yet, and all of them use the latest stable version. If you cannot install it using the following method, I have compiled the Ubuntu software package. You can get other operating system versions from the comments.

?

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

Let's start with Django Project

?

1

2

3

Django-admin.py startproject realtime_tutorial & cd realtime_tutorial

Python manage. py startapp core

Mkdir nodejs

After the preceding code is executed, the django project is configured. The next step is to set the database in the settings file. Create a blank database first. (This is an example of setting file. Add a "core" in my app and configure the templates and urls paths. You can modify the configuration information in settings at will, but it must correspond to your app.

Model

Models is simple. We will create a table containing user and text. If you want to make it more complex, you can add information such as chatroom. (For the sake of simplicity, only two are written here)

?

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)

This is the model we will use. Next we will execute the following syncdb Code (the first line of code) to create a database. Then create several users for testing. (Line 2 code)

?

1

2

3

4

Python manage. py syncdb

Python manage. py createsuperuser

 

Node Server With Socket. IO

This section describes how to send and obtain real-time information. Use Node. js to create an app server that depends on Socket. IO, and use Redis for this task. Create a file named "chat. js" in the nodejs dictionary and put it here:

?

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 ('cooker ');

Var querystring = require ('querystring ');

 

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

Var sub = redis. createClient ();

 

 

// Subscribe to chat channel

 

 

Sub. subscribe ('chat ');

 

 

// Configure socket. io to store the cookie set by Django

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 ){

 

// Send the information from Redis to the client

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

Socket. send (message );

});

 

// The client sends messages through 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

}

};

 

// Use Django server to send messages

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

Res. setEncoding ('utf8 ');

 

// Output error message

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

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

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

}

});

});

 

Req. write (values );

Req. end ();

});

});

First, import and create an http server to listen to port localhost 4000. Then subscribe to Redis's "chat" chanel. Finally, we only need to call it in Django view.

Last time we set the Django setting where Socket. IO can use cookies in the local field, which allows us to access cookie data through socket. handshake. cookie. How can we get the user's session.

We set Socket. i/O cookies can only be held after many events. The first event is the Redis release channel. When our users notice that a new message has been notified that it will send a message to clients on all sites.

Another event is that when the client sends a message through Socket. IO, we use the string query module to create a query to be sent to our Django service. Our Django service will run on the local port 3000, but you can change that requirement. Set the path to the/node_api URL. We will soon create it next to Django. Once queryString is sent, Django will save the relevant components and return "Everything worked (all working)" to us )". If no output error is returned to us, close the node console.

A node that does not use Redis

You really don't have to use Redis for this project. I found it will be a good learning experience. If you want to divert Redis, you can create a channel, use expressions or some other class libraries, the code above will receive a message from Django. When a comment is saved, you can use Socket. add comments to all clients for IO

Template

This is where all of our HTML and javascript are placed. It allows us to display comments and interact with our Node service.

?

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>

On the above page, we use socket. IO to connect to our node service on the local port 4000. When we get an information from the server, we will perform some escaping in the directory and add it to our annotation list, when we want to send a message, we will perform a corresponding 13 (press the next key) key check on the input box. Once it is pressed, we send a message to the server to make it held. Once it is saved by Django to our database, we will get a "message" event to add it to our session List.

Our Django shows that we will load a "comments" variable in the next step, so we set and traverse all the following loops in that way. This part is only used when the page is initially loaded. Our javascript will add data to this directory as a new data from our Node service.

View

Open realtime_tutorial/core/views. py and edit it like me:

?

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:

# Get the user through sessionid

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)

 

# Create Comment

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

 

# Send it to the chat room after creation

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

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

 

Return HttpResponse ("Everything worked :)")

Except t Exception, e:

Return HttpResponseServerError (str (e ))

Let's see what happened here. Home is a standard view File. Use select_related to obtain the username of each comment, instead of returning a comment query set when the page is loaded for the first time.

The second is the view of the information sent by the Node app. We get the sessionid from POST, and then get the userid through decoding. After confirming that the user exists, you can create a comment. Now, send username and comment to the Redis server. Finally, send the data to the channel called "chat.

URLs

This is relatively simple, because we will use the views and template that comes with Django.

?

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!

Open 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

I put the code on github. If you want to make it better, you can allow users to create and join chat rooms. You can also use PHP or Rails for development.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.