지금까지 하면서의 장고프레임웍의 장점과 단점

Computer 비관심/Django|2017. 2. 23. 21:07
반응형

지극히 주관적인 의견이다.


파이썬을 1월에 시작해서 1월 말에 장고를 처음 시작했다. 약 한달 가까이 장고를 하면서 느낀점이다. 참고로 아직 django를 깊게 다루지 못한것 같다. 이전에는 잘하지는 않지만 wordpress, nodejs express framework와 프레임워크를 사용하지 않은 php에 대한 경험이 있다. 


장고의 단점부터 말하자면 개인적인 의견으로 처음 웹을 배운다고 하면 php가 가장 난이도가 쉽다고 생각한다. 처음으로 컴퓨터를 배울때 사용한 언어가 php였는데 확실히 쉬웠다. 배운지 한달만에 커뮤니티사이트를 만들 수 있었다. 반면에 장고는 러닝커브가 높다. 개인적으로도 일반적인 사용자의 의견도 다른 프레임웍 보다 어렵다고 한다. 프레임워크라는 것에 대한 개념을 익혀야 하며 객체지향을 어느정도 이해해야 수정을 하며 사용할 수 있다. 물론 튜토리얼을 따라하며 만들 수는 있지만 객체지향에 대한 이해가 없으면 사용하기가 어렵다. 

처음에 장고의 orm을 사용하면서 왜 이것을 사용해야 하는가라는 생각이 들었다. mongodb의 쿼리와 비슷한데 차라리 몽고디비의 쿼리를 익히는게 더 도움이 되지 않을까라는 생각도 들었고 SQL을 ORM레이어를 거치치 않고 직접 쓰는것이 더 효율적이라고 생각했다. 즉 이러한 것들의 장점을 알아야 하는데 기존의 프로그래밍적인 지식이 없이는 이해하기 어려운 것이다. 



장점은 프레임웍을 익히기만 하면 더 빠른 속도로 개발을 할 수 있도록 도와준다. 기본으로 어드민을 제공해준다. admin을 만드는 것은 귀찮은 일이다. 그래서 만들지 않은적도 많다. 장고는 어드민을 기본으로 지원해준다. 그 어드민에서 다양한 옵션들을 추가하여 다양한 기능을 하는 어드민을 만들 수 있다. generic class를 제공한다. 웹사이트에서 자주 사용하는 기능들이 이미 클래스로 만들어져 있다.

form 도 지원해 준다. 자동으로 html폼이 만들 수 있는 forms를 제공한다. orm(object relational mapper)를 제공함으로서 다양한 데이타베이스에서 SQL을 바꾸지 않고 사용이 가능하며 더 쉽게 사용가능하다.


깃을 이해하지 못했는데 장고를 사용하고나서 깃이 어느정도 이해 되었다;;;; makemigration과 add, migrate와 commit이 비슷하게 느껴진거 같다. ㅎㅎ

마지막으로 파이썬을 사용한다. 파이썬은 배우기가 쉽고 문법도 간결하다. 그리고 다양한 과학분야에서 사용됨으로 그에 따른 라이브러리가 다양하다.  

댓글()

[4]장고 채널스(django channels) json 데이타 전송

Computer 비관심/Django|2017. 2. 18. 00:01
반응형

콘슈머에 json과 parse를 임포트 한다. 지금까지 text: message.content['text'] 로 돌려보냈는데 이번에는 text: json.dumps()를 사용하여 데이타를 브라우저에 json 형태로 보낸다. 영문 튜로리얼과 다르게 우리는 한국말을 사용하기 때문에 , ensure_ascii=False를 붙여주어 한글이 아스키코드로 바뀌어서 나오는 것을 막았다.

# consumers.py

import json
from urllib import parse

from channels import Group
from channels.sessions import channel_session


@channel_session
def ws_add(message, room):
    query = parse.parse_qs(message['query_string'])
    if 'username' not in query:
        return
    Group('chat-%s' % room).add(message.reply_channel)
    message.channel_session['room'] = room
    message.channel_session['username'] = query['username'][0]


@channel_session
def ws_echo(message):
    if 'username' not in message.channel_session:
        return
    room = message.channel_session['room']
    Group('chat-%s' % room).send({
        'text': json.dumps({
            'message': message.content['text'],
            'username': message.channel_session['username']
        }, ensure_ascii=False),
    })

콘솔에 웹소켓을 ws://localhost:8000/chat/1?username=sean 이런 형식으로 보낸뒤 아래와 같은 방식으로 브라우저 마다 여러개를 만들면 서버에서 메시지와 함게 세션에 저장된 usernamed을 함께 보내는 것을 확인 할 수 있다.

ws = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') +  window.location.host + '/chat/' + 1 + '?username=' + 'sean');
//메시지가 오면 콘솔
ws.onmessage = function(message) {
      console.log(message.data);
    }
ws.send('hi')
1번 브라우저에서는 션이라고 만들었고 2번째 브라우저에서는 jone이라고 만들어서 메시지를 보낸 것을 확인 할 수 있다.


댓글()

[3] 장고 채널스(django chennals) urls를 기반으로 한 라우팅

Computer 비관심/Django|2017. 2. 17. 15:48
반응형

우리가 이전에 만든 route에 path 를 다음과 같이 추가한합니다.

그러면 url로 consumers.ws_add를 실행 할 수 있다. 이것은 인자를 ws_add로 넘기는 방법은 urls.py 에서 한 방법과 같습니다.

# routing.py

channel_routing = [
    ...
    route('websocket.connect', 'chat.consumers.ws_add',
          path=r'^/chat/(?P<room>\w+)$'),
]

consumers.py를 수정합니다. channel_session을 불러오고 @channel_session 데코레이터를 붙이면 장고 세션처럼 사용할 수 있는 message.channel_session을 제공합니다.

아래코드에서는 소켓접속시 room이라는 인자를 전달받아 'chat-전달받은 인자' 방을 만들고 

message.channel_session['room'] = room으로 세션을 저장하고 메시지가 전달되면 저장된 세션을 가져와 chat-인자 방에 send해줍니다.


# consumers.py

from channels import Group
from channels.sessions import channel_session


@channel_session
def ws_add(message, room):
    Group('chat-%s' % room).add(message.reply_channel)
    message.channel_session['room'] = room


@channel_session
def ws_echo(message):
    room = message.channel_session['room']
    Group('chat-%s' % room).send({
        'text': message.content['text'],
    })

테스트로 브라우저를 열고 소켓 객체를 생성해봅니다.


// 소켓생성
var ws1 = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') + window.location.host + '/chat/' + 1) // 아이디 생성 ws1.id = 1; // 메시지가 오면 콘솔에 출력하도록 함. ws1.onmessage = function(message) { console.log('W' + this.id + ': ' + message.data); }

다른 브라우저에

// 소켓생성
var ws2 = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') + window.location.host + '/chat/' + 2) // 아이디 생성 ws2.id = 2; // 메시지가 오면 콘솔에 출력하도록 함. ws2.onmessage = function(message) { console.log('W' + this.id + ': ' + message.data); }

또 다른 브라우저에 

// 소켓생성
var ws3 = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') + window.location.host + '/chat/' + 2) // 아이디 생성 ws3.id = 3; // 메시지가 오면 콘솔에 출력하도록 함. ws3.onmessage = function(message) { console.log('W' + this.id + ': ' + message.data); }


결과


1번 브라우저

ws1.send를 할때 자기 /chat/1 그룹으로 등록한 사람에게만 보냈다. 1번 소켓 하나만 등록음. 


2번 브라우저



3번 브라우저


2번 소켓 3번 소켓은 chat/2 그룹으로 등록하여 2번 소켓이 send를 했을때 3번 소켓도 같이 데이타를 받는 것을 볼 수 있다.



같은 소켓을 하나의 브라우저에서 두번 만드는 것도 가능하다.


댓글()

[2] 장고 채널스(django chennals) Group

Computer 비관심/Django|2017. 2. 17. 13:05
반응형

Group의 개념


urls의와 비슷한 개념의 routing.py에 이번에는 websocket.connect를 추가합니다.

websocket.receive는 소켓에 message가 전달 됬을때 발생하며

websocket.connect는 소켓에 소켓이 생성됬을 때 발생합니다. 

#routing.py

channel_routing = [
    route('websocket.receive','chat.consumers.ws_echo'),
    route('websocket.connect', 'chat.consumers.ws_add'),
]

그러면 consumers.py에서 ws_add를 만들고 그룹에 있는 사람들이 메시지를 모두 받을 수 있도록 ws_echo를 수정해 보겠습니다. 

이전 글에서도 말했듣이 consumers.py는 장고의 views.py와 비슷하다고 볼 수 있습니다.  


ws_add에서는 routing.py에 websocket.connect가 실행되면 Group('chat')이라는 객체를 만든뒤 웹소켓 연결을 통해 만들어진 인스턴스들을 추가합니다.


ws_echo도 Goup('chat').send({text:브라우저로 보낼내용})

# consumers.py

from channels import Group


def ws_add(message):
    Group('chat').add(message.reply_channel)


def ws_echo(message):
    Group('chat').send({
        'text': message.content['text'],
    })


소캣객체 생성부터 메시지보내기 까지 3번 반복~

for (var i = 0; i < 3; ++i) {
  // Create a new WebSocket
  var ws = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') +  window.location.host + '/')
  // Assign it an id
  ws.id = i;
  // Make it show a console message when a message is received
  ws.onmessage = function(message) {
    console.log('W' + this.id + ': ' + message.data);
  }
  // Send a new message when the WebSocket opens
  ws.onopen = function() {
    this.send('Hello, world');
  }
}

소켓을 만들고 ws.onmessage 즉 메시지가 왔으면 console.log를 사용해 message.data의 내용을 console에 뿌려준다.

ws.send는 서버에 내용을 hellow,world를 전달해준다.

댓글()

[1] 장고 채널스(django channels) 웹소켓 에코

Computer 비관심/Django|2017. 2. 17. 10:28
반응형


장고 채널은 장고 1.10 이상에서 지원


1.설치

# requirements.txt

asgi-redis==1.0.0
channels==0.17.3
daphne==0.15.0
Django==1.10.4

requirements.txt 파일을 만든 뒤 pip install -r requirements.txt를 입력하여 requirements.txt에 있는 모듈을 모두 설치 한다.




2. 앱 세팅


- 프로젝트를 만들고 앱을 만든다. 


- settings.py의 INSTALLED_APPS에 channels와 새로 생성한 앱 추가한다. (여기선 앱의 이름을 chat 이라고 만듬)

# settings.py

INSTALLED_APPS = (
    ...
    'channels',
    'chat',
)

...

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'asgiref.inmemory.ChannelLayer',
        'ROUTING': 'django_channels.routing.channel_routing',
    },
}

3.routing


- 라우팅 처리를 위하여 위에 설정한 바와 같이 django_channels라는 폴더에 routing.py 파일을 만든다.  


# routing.py
from channels.routing import route

channel_routing = [
    route('websocket.receive', 'chat.consumers.ws_echo'),
]

4. consumers.py


# consumers.py

def ws_echo(message):
    message.reply_channel.send({
        'text': message.content['text'],
    })


소켓이 접속이 되는지 확인하기 위해 로컬호스트에 접속하여 소켓을 만들어 아래를 입력합니다.


// http인지 https인지 확인 하여 그것에 맞는 소켓을 웹소켓 프로토콜을 선택
var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
ws = new WebSocket(ws_scheme +'://' +  window.location.host + '/');


이렇게 소켓에 접속 된 것을 볼수 있습니다.


// Create a new WebSocket
ws = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') +  window.location.host + '/')

// ws.onmessage를 통해 메시지를 받으면 알림
ws.onmessage = function(message) {
  alert(message.data); 
}
// ws.onpen을 통해 소켓이 열리면 메시지를 보냄
ws.onopen = function() {
  ws.send('Hello, world');
}

send의 키를 text라고 하고 키 값으로 브라우저에 보낼 내용을 적습니다. 아래의 예는 브라우저에서 보낸 내용을 매개변수 message로 받아 오브젝트를 생성하여 .content['text']로 브라우저에서 보낸 내용을 다시 브라우저에 전달 하였습니다.


content 딕셔너리의 text라는 키가 있음. 그 키에는 브라우저에서 보내온 값이 있다.


message오브젝트에 data속성에 채널에서 보낸 내용이 들어 있다.


ws.readyState 를 통해 소켓의 상태를 확인 할 수 있음.  

WebSocket.OPEN  ->1 반환 소켓이 열려있음 

WebSocket.CLOSED ->3 반환 소켓이 닫힘


※ 이대로 하면 websocket.receive이 작동안됨을 알 수 있다. 이유는 다음과 같다.

위의 모듈대로 설치하게 되면  Twisted 가 최신버전으로 깔리게 되는데 Twisted 16.2.0만 제대로 작동한다는 이야기가 있다.

즉, 제대로 작동하기 위해서는 Twisted를 지운뒤 16.2.0버전으로 다시 설치하여야 한다.





참고


글이 적어서 좋았던 튜토리얼

https://www.sourcelair.com/blog/articles/115/django-channels-chat

소켓연결에서 http와 https에 따른 ws와 wss 선택  

https://blog.heroku.com/in_deep_with_django_channels_the_future_of_real_time_apps_in_django

채널 공식 문서

https://media.readthedocs.org/pdf/channels/latest/channels.pdf

twisted 문제 

http://stackoverflow.com/questions/38322197/django-channels-websocket-receive-is-not-handled



댓글()

[동영상 녹화 프로그램 추천] obs 스튜디오

기타|2017. 2. 11. 00:48
반응형

댓글()

[requests.post] python으로 보낸 데이터 php로 받기

카테고리 없음|2017. 2. 11. 00:41
반응형

python으로 보낸 데이터 php로 받기



인터넷에서 python에서 데이타를 보내는 예제를 많이 찾아 볼 수 있다. 하지만 문제는 파이썬3.x버전에서는 사용해야 하는 모듈이 인터넷에 나온 기존 예제와 다르다는 것이다. 또한 데이타베이스에 저장을 하는 것이 아닌 쿠키를 생성함으로써 데이타가 잘 전송되는지 알아보려고 하는 실수 때문에 시간이 오래 걸렸다.


작동되는 코드는 다음과 같이 간단하다.



import requests

userdata = {"firstname": 'frompython', "lastname": "Doe", "password": "jdoe123"}

resp = requests.post('http://localhost/test/testing.php', data=userdata)

print(resp.text)

 





1. 딕셔너리 형식으로 데이타를 변수에 저장한 뒤 

2. requests.post를 사용하여 데이타를 처리하는 페이지에 전달을 한다.

다음은 이것을 처리하는 php서버 코드이다.


<?php 

if(isset($_POST['firstname'])){

   $name = $_POST['firstname'];

   $conn=mysql_connect("localhost","root","");

   if(!$conn){

   die('could not connect:'.mysql_error());

   }

   mysql_select_db("test",$conn);

   $query ="INSERT INTO testing (data) VALUES ('$name');";  

   // '$name에서' '' 이거 빠뜨리지 않게 조심해야함. 쿠키는 클라이언트에서 생성함으로 여기서 만들어지지 않음


   $result = mysql_query($query, $conn);  

   setcookie("name", "$name", time()+5000);

   echo "$name";

}else{

   echo("nothing");

}


 ?>



처음에 데이타가 제대로 전송이 되는지 확인하기 위해 쿠키를 생성하려고 하였지만 쿠키는 클라이언트에서 생성하기 때문에 생성이 되지 않았다. 하지만 데이타베이스에 저장하는 코드를 적으니 데이타베이스에 값이 저장 되는 것을 볼 수 었다. 



----- 추가 -----

import urllib

import urllib2


url = 'http://xxx.xxx.x.xxx/reciever.php'

payload = {"device":"gabriel","data_type":"data","zone":1,"sample":4,"count":0,"time_stamp":"00:00"}

headers = {'content-type': 'application/json'}    

data = urllib.urlencode(payload)

req = urllib2.Request(url, data, headers)

response = urllib2.urlopen(req)

the_page = response.read()




구글링할때 가장 많이 보는 코드인데 

3.0버전에서는urllib2가 분리되어서 작동하지 않는다. 아래 처럼 코드를 작성하면 request가 아닌 urllib로 urllib2를 대신 할 수 있다.


import urllib.request 

userdata = {"firstname": "John", "lastname": "Doe", "password": "jdoe123"} 

userdata = urllib.parse.urlencode(userdata) 

binary_data = userdata.encode('utf-8') 

resp = urllib.request.urlopen('http://localhost/test/testing.php', binary_data) 


댓글()

함수의 스코프

Computer 비관심/PyQt5|2017. 1. 22. 01:30
반응형

자바스크립트 함수에서 전역변수로 사용한 경우



var로 선언하여 로컬변수로 선언하였더니 전역변수에 영향을 미치지 않았다.



파이썬의 함수안 로컬변수는 전역변수에 영향을 주지 않는다. 그러므로 함수가 실행이 끝난뒤 로컬 변수는 사라진다. 영향을 주고 싶다면 함수네에서 global로 변수를 선언해야 한다.





하지만 리스트나 딕셔너리는 레퍼런스를 하므로 영향을 받는다. 

댓글()