파이썬 가상 환경 설정 및 장고 설치하기

[markdown]
갑자기 회사의 동료가 나에게 장고스터디를 해달라고 했다. 마침 장고를 보고있었던 나는 쥐뿔도 모르지만, 이제부터 준비하려고 장고를 열심히 보고 있다.  근데, 나쁜버릇이 나와서 설치부터 잘하고 싶은 마음이 드는 것이다.

남들은 그냥 `sudo pip install django` 이렇게 하고 넘어갔을 것을 괜시리 깔끔떨며 가상환경이라는 것을 만들어보기로 한다. 그럼 같이 한삽을 같이 퍼보도록 하자.

아래에서 실행한 스크립트들은 **virtualbox에 새로 설치한 ubuntu14.04 LTS**에서 아주 깔끔한 상태로 실행한 것들이다.  다른 Linux에서는 설치하는게 비슷하거나 약간 다를것이고, windows에서는 아~~주 많이 다를것이다. 그러므로 그점을 인지하고 보도록 하자.

사실 OSX는 예전에 정리해놓은 글이 있다. 똑같은걸 두번이나..적다니..ㅠㅠ

[맥에서 쟝고개발환경 만들기](http://gyus.me/?p=240)

###우분투에서 python3 설치
`sudo apt-get install python3-all`

###pip 설치
`sudo apt-get install python-pip `

###virtualenv 설치
virtualenv를 설치하는 이유는 여러가지가 있지만, 내가 아는 바로는 아래 4가지다.

– 파이썬 패키지를 설치할 때 관리자 권한이 아니라 유저 권한으로 설치 하고 싶음.
– 파이썬의 실행 환경을 리눅스의 것과 온전히 구분해서 서버를 깔끔하게 하고 싶음.
– python3을 실행할 때 그냥 python으로 실행하고 싶음.
– 개발환경과 실서버환경을 동일하게 맞추고 싶음.

그럼 설치해보자. (간단간단)

`sudo pip install virtualenv`

###virtualenvwrapper 설치
뭘 이런 헷갈리는걸 또 설치하냐고 물어볼 사람이 있을 것 같은데(나도 그랬음), 그냥 세트라고 생각하고 설치하는게 좋다. virtualenv를 훨씬 사용하기 간편하게 해준다.

`sudo pip install virtualenvwrapper`

###virtualenv 환경 설정
1. 디폴트 디렉토리 만들기 .virtualenv
mkdir ~/.virtualenvs
2. WORKON_HOME 환경 변수에 디폴트 디렉토리 등록하기
export WORKON_HOME=~/.virtualenvs
3. .profile(우분투 기준 유저 로그인시 실행되는 스크립트) 에 virtualenvwrapper를 임포트 하도록
위 파일의 가장 하단에 아래 스크립트 추가

`. /usr/local/bin/virtualenvwrapper.sh`
혹은
`source /usr/local/bin/virtualenvwrapper.sh`

###가상환경 만들어보기

위의 과정을 잘 따라했다면 `virtualenvwrapper.sh` 내에 있는 함수인 `mkvirtualenv` 함수를 사용할 수 있다.

`mkvirtualenv {{가상환경-이름}}`
요렇게 사용한다

`mkvirtualenv py2`

요렇게하면 py2라는 이름의 가상환경이 설치되고 그 가상환경을 사용할 수 있게(workon) 된다.

`which python`
명령어를 실행했을 때 아래와 같은 경로로 나오면 제대로 된것이다.
`/home/user_name/.virtualenvs/py2/bin/python`

가상환경에서 나가려면
`$ deactivate`
와 같이 실행한다

다시 들어가려면
`$ workon py2`
라고 하면된다.

###그럼 python3의 가상환경을 만들고 싶으면?

`virtualenv`가 인식하는 환경변수중에 `VIRTUALENV_PYTHON` 이라는 환경변수가 있는데, 저 변수에 `python3`의 경로를 넣어 주면 된다.

이렇게 해보자.
“`
export VIRTUALENV_PYTHON=`which python3`
mkvirtualenv py3
“`

이렇게 하면 환경변수 안쓰고도 된다!(이진석님 감사합니다.)
“`
mkvirtualenv py3 –python=`which python3`
“`
물론 위의 `which python3`이 제대로 되려면 `python3`이 설치가 되어있어야 한다.
(`sudo apt-get install python3-all`을 위에서 실행한 이유가 그것 때문)

이렇게 하면 파이썬3의 환경으로 가상환경이 만들어졌다.
파이썬 버젼을 확인해보자.
`(py3) ~ $ python -V `
`Python 3.4.0`

요런식으로 나오면 성공~!
긜고 pip3도 pip 로 실행된다.

####아..이제 환경설정이 됐으니 장고를 설치할 수 있다…;;;

### 장고설치
쟝고의 설치는 허무하게도 아래의 한줄

`pip install django`

장고 설치끝~
[/markdown]

Django tutorial1

[markdown]
#django 튜토리얼1

###쟝고의 기능들
– ORMapper
– Automatic admin interface
– Elegant URL design
– Template system
– cache system
– Internationalization

###쟝고 설치됐는지 확인하기

`python -c “import django; print(django.get_version())”`

###project 만들기

`django-admin.py startproject mysite`

위에꺼 실행하면 아래와 같은 디렉토리 & 파일이 생성됨

“`shell
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
“`

– manage.py : 커맨드라인 유틸리티. 자세한 것은 다음링크에서 확인가능 [django-admin.py and manage.py](https://docs.djangoproject.com/en/1.6/ref/django-admin/)
– mysite 디렉토리 안의 mysite : 디렉토리가 실제 만들게될 프로젝트의 디렉토리
– mysite/settings.py : 쟝고프로젝트 설정파일. 자세한 것은 다음 링크에서 [Django settings](https://docs.djangoproject.com/en/1.6/topics/settings/)
– mysite/urls.py : 쟝고프로젝트의 URL정의 파일. 자세한 것은 다음 링크에서 확인 [URL dispatcher](https://docs.djangoproject.com/en/1.6/topics/http/urls/)
– mysite/wsgi.py : WSGI과 호환되는 웹서버의 시작점. 자세한 것은 다음 링크로 [How to deploy with WSGI](https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/)

##### 서버기동
`python manage.py runserver`

##### 데이터베이스 세팅
디폴트는 sqlite3이고, 다른 데이터베이스를 사용하려면 mysite/settings.py의 `DATABASES` 부분을 수정해주어야한다. (나는 mongodb쓸껀데…) 데이터베이스 세팅에 관한 내용은 다음 링크에 있음 [setting-DATABASE-ENGINE](https://docs.djangoproject.com/en/1.6/ref/settings/#std:setting-DATABASE-ENGINE)

##### 타임존 설정(TIME_ZONE)
나는 대한민국 사람이니 mysite/settings.py 의 TIME_ZONE을 ‘Asia/Seoul’로 변경함. 기본은 ‘America/Chicago’
언어는 귀찮아서 냅둠.

##### 설치된 앱들

settings.py에 보면 INSTALLED_APPS라는 파라메터가 있는데, 현재의 쟝고 인스턴스에서 활성화 된 쟝고 어플리케이션의 이름들을 적어놓은 곳이다. APP은 여러 프로젝트에서 사용가능하고 패키징하고 배포가 가능해서 다른 프로젝트에서도 사용될 수 있다.

디폴트로 포함되어 있는 앱들

– django.contrib.admin – 관리자페이지
– django.contrib.auth – 인증시스템
– django.contrib.contenttypes – 컨텐트타입 프레임웤
– django.contrib.sessions – 세션 프레임웤
– django.contrib.messages – 메세징 프레임웤
– django.contrib.staticfiles – 정적파일을 위한 프레임웤

##### syncdb
`$ python manage.py syncdb`

syncdb 커맨드는 INSTALLED_APPS의 설정을 보고 필요한 데이터베이스 테이블을 생성한다.
처음 실행할때 admin유저를 만들 수 있다.

##### app 만들기
`python manage.py startapp polls`

mysite의 탑레벨 모듈로 polls모듈을 만들자.

디렉토리는 아래와 같이 생겼다.

“`shell
polls/
__init__.py
admin.py
models.py
tests.py
views.py
“`

##### 모델만들기

polls/models.py 를 아래와 같이 고친다.

“`python
from django.db import models

class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField(‘date published’)

class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
“`

하나의 클래스는 테이블과 매핑되고 하나의 변수는 하나의 필드와 매핑이 된다. 그리고 Choice클래스에 외래키를 지정했는데 django는 관계형디비의 모든 관계(다대다 일대다 일대일)를 지원한다.

##### 모델 활성화하기

mysite/settings.py의 파일을 다시 열어서 아래와 같이 수정한다.

“`python
INSTALLED_APPS = (
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
‘polls’,
)
“`

이제 쟝고가 polls앱이 포함된 것을 알게됐다. 다음으로 아래의 명령을 실행해보자.

`$ python manage.py sql polls`

그러면 아래와 같은 SQL문이 콘솔에 찍힌다.

“`sql
BEGIN;
CREATE TABLE “polls_poll” (
“id” integer NOT NULL PRIMARY KEY,
“question” varchar(200) NOT NULL,
“pub_data” datetime NOT NULL
)
;
CREATE TABLE “polls_choice” (
“id” integer NOT NULL PRIMARY KEY,
“poll_id” integer NOT NULL REFERENCES “polls_poll” (“id”),
“choice_text” varchar(200) NOT NULL,
“votes” integer NOT NULL
)
;
“`

– 콘솔에 찍힌 SQL은 우리가 지정한 혹은 기본인 sqlite3 데이터 베이스에 사용되는 SQL문임을 알 수 있다.
– 테이블명은 자동적으로 app(polls)과 소문자 모델클래스명을 결합하여 만들어진다.
– 프라이머리키(IDs)는 자동으로 추가된다. (오버라이딩 가능)
– 관례로, 쟝고는 ‘_id’를 외래키명에 붙인다.
– 외래키 관계는 REFFERNCE문으로 정확히 만들어졌다.
– `sql`명령어는 실제로 SQL을 실행하지는 않고 단순히 출력만 해준다.

관심있으면 아래 명령어도 테스트해보길

– python manage.py validate – 모델이 유효한지 체크해줌
– python manage.py sqlcustom polls – 테이블 변경이나 제약수정을 위한 명령어를 출력
– python manage.py sqlclear polls – 테이블 삭제를 위한 쿼리를 출력
– python manage.py sqlindexes polls – 인덱스 생성문을 출력
– python manage.py sqlall polls – 해당앱에 사용된 모든 쿼리를 합쳐서 출력

`syncdb`로 모델의 테이블을 생성하자! (syncdb는 create만 해주고 alter는 해주지 않는다. 만약에 컬럼명이 변경된 경우 수동으로 고쳐야함)

### API로 놀기

`$ python manage.py shell` managy.py가 DJANGO_SETTINGS_MODULE의 환경을 세팅해줌

“`python
>>> from polls.models import Poll, Choice
>>> Poll.objects.all()
[]

>>> from django.utils import timezone
>>> p = Poll(question=”What’s new?”, pub_date=timezone.now())
>>> p.save()
>>> p.id
1

>>> p.question
“What’s new?”
>>> p.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=)

>>> p.question = “What’s up?”
>>> p.save()

>>> Poll.objects.all()
[]
“`

마지막에 Poll object라고 나온거는 전혀 도움이 안되니 도움이 되는 문자열로 만들어보자.

polls/models.py 에 다음과 같은 메서드를 추가해주면 됨

“`python
from django.db import models

class Poll(models.Model):
# …
def __unicode__(self): # Python 3: def __str__(self):
return self.question

class Choice(models.Model):
# …
def __unicode__(self): # Python 3: def __str__(self):
return self.choice_text
“`

메서드 하나를 또 추가해보자

“`python
import datetime
from django.utils import timezone
# …
class Poll(models.Model):
# …
def was_published_recently(self):
return self.pub_date >= timezone.now() – datetime.timedelta(days=1)
“`

`python manage.py shell`을 다시실행해서 놀아보자

“`python
>>> from polls.models import Poll, Choice

# Make sure our __unicode__() addition worked.
>>> Poll.objects.all()
[]

>>> Poll.objects.filter(id=1)
[]
>>> Poll.objects.filter(question__startswith=’What’)
[]

# Get the poll that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Poll.objects.get(pub_date__year=current_year)

# Request an ID that doesn’t exist, this will raise an exception.
>>> Poll.objects.get(id=2)
Traceback (most recent call last):

DoesNotExist: Poll matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)

>>> p = Poll.objects.get(pk=1)
>>> p.was_published_recently()
True

>>> p = Poll.objects.get(pk=1)

>>> p.choice_set.all()
[]

>>> p.choice_set.create(choice_text=’Not much’, votes=0)

>>> p.choice_set.create(choice_text=’The sky’, votes=0)

>>> c = p.choice_set.create(choice_text=’Just hacking again’, votes=0)

>>> c.poll

>>> p.choice_set.all()
[, , ]
>>> p.choice_set.count()
3

>>> Choice.objects.filter(poll__pub_date__year=current_year)
[, , ]

>>> c = p.choice_set.filter(choice_text__startswith=’Just hacking’)
>>> c.delete()
“`

여기까지 했으면 인제 파트2로 넘어가도 됨. (튜토리얼은 6개까지 있음)
[/markdown]

[python] private / public아이피 구분하는 스크립트

아이피가 퍼블릭인지 사설아이피인지
구분해야할 필요가 있어서, 쉘스크립트로 만들려고 찾아보다가
포기하고 쉘에서 스크립트언어를 불러오는 방법으로 변경했다.

요즘 루비를 공부중인지라 루비로 만들고 싶었지만,
회사의 서버에는 루비가 거의 설치가 안되어 있는지라

회사의 서버에 대부분 설치 되어 있는 파이썬으로 만들었다.

첨에는 어떻게 해야되는지 좀 막막했는데,
아래 링크의 소스를 보니 그렇게 어렵지 않았다.
파이썬의 소스도 아래링크의 php소스를 파이썬으로 변경한것이다.

Check private IP function PHP

그리고 스택오버플로우에 무지하게 간단한 방법이 있긴했는데,
뭔가 모듈을 설치해야되는것 같았다.
http://stackoverflow.com/questions/691045/how-do-you-determine-if-an-ip-address-is-private-in-python

그래서 그냥 php소스를 python으로 변경하는것으로 최종 결정했다.

아래는 포팅한 소스이다.
파이썬을 잘하는 편이 아닌지라 되도록 간단히 만들려고 노력했다.

원리는 ip를 long타입으로 변환해서 privateip구간에 있는지 체크하는 원리이다.
뭔가 더 좋은게 있을것 같긴한데…(아시는분은 코멘트 좀 부탁드려요.^^)

isPrivateIp.py

import sys
from struct import *
from socket import *

if len(sys.argv) != 2:
    print "input just one parameter."
    sys.exit()

input_ip = sys.argv[1]

private_addrs = ['10.0.0.0|10.255.255.255',
                 '172.16.0.0|172.31.255.255',
                 '192.168.0.0|192.168.255.255',
                 '169.254.0.0|169.254.255.255',
                 '127.0.0.0|127.255.255.255'
                 ]

def ip2long(ip_addr):
    ip_packed = inet_aton(ip_addr)
    ip = unpack("!L", ip_packed)[0]
    return ip

def isPrivateIP(ip_addr):
    long_ip = ip2long(ip_addr)
    if long_ip != -1:
        for private_addr in private_addrs:
            start, end = private_addr.split("|")

            if long_ip >= ip2long(start) and long_ip <= ip2long(end):
                return 'PRIVATE'

    return 'PUBLIC'

print(isPrivateIP(input_ip))

쉘에서 사용하는 경우

IP_TYPE="`python ${DEPLOY_HOME}/isPrivateIp.py $IPADDR`"
echo "IP type is $IP_TYPE"

if [ "$IP_TYPE" == "PRIVATE" ];then
	echo "PIVATE IP!"

fi