Django+MongoDB開発環境整備 (書き途中)

## 環境
- Mac OS X Lion
- virtualenv
- virtualenvwrapper
- GitHub
- python 2.7
- Django 1.3


##インストール
### virtualenv作成
```
mkvirtualenv -p /usr/bin/python2.7 [プロジェクト名]
```

### Django+MongoDBインストール
```
pip install git+https://github.com/django-nonrel/django-nonrel.git@master
pip install git+https://github.com/django-nonrel/djangotoolbox.git@master 
pip install git+https://github.com/django-nonrel/mongodb-engine.git@master
```

### py.testインストール
```
pip instal py.test
pip install django_pytest
```


## プロジェクト作成
```
cd [devディレクトリ]
workon [プロジェクト名]
django-admin.py startproject [プロジェクト名]
```


## ディレクトリ構造
```
cd [プロジェクトルート]
# アプリケーション配置用
mkdir apps
touch apps/__init__.py
# テスト用データなど
mkdir fixtures
# 国際化対応po/moファイル置き場
mkdir -p local/ja/LC_MESSAGES
mkdir -p local/en/LC_MESSAGES

# Put project-specific requirements here.
# See http://pip-installer.org/requirement-format.html for more information.
mkdir requirements

# This directory is used to store static assets for 
# your project. User media files (FileFields/ImageFields) are not stored here.
mkdir static
mkdir static/img
mkdir static/js
mkdir static/css

# テンプレート置き場
mkdir templates

# ドキュメント置き場
mkdir docs
```


## アプリケーション作成
```
cd [プロジェクトルート]/apps
# モデル配置用
django-admin.py startapp models
```


## GitHub登録
```
cd [プロジェクトルート]
git config --global user.name  "ユーザ名"
git config --global user.email  "メールアドレス"
git init
git add *.py
git add app
git commit -m 'first commit'
git remote add origin git@github.com:USER_ID/REPO_NAME.git
git push -u origin master
```


## MongoDBの準備
### サーバ設定
#### ディレクトリと設定の作成
```
mkdir -p environment/dev/var/mongodb
mkdir -p environment/dev/etc

# 設定ファイル作成
cat <<EOF >> environment/dev/etc/mongod.conf
heredoc> # Store data
heredoc> dbpath = [プロジェクトルート]/environment/dev/var/mongodb
heredoc> 
heredoc> # Only accept local connections
heredoc> bind_ip = 127.0.0.1
heredoc> EOF

# 開発用DBがgitに入らないようにする
cat << EOF >> environment/dev/var/mongodb/README
heredoc> 開発用MongoDBデータ置き場  
heredoc> EOF

cat << EOF >> environment/dev/var/mongodb/.gitignore
heredoc> /*
heredoc> /.*
heredoc> !README
heredoc> !.gitignore
heredoc> EOF
```

#### サーバ起動
```
mongod run --config environment/dev/etc/mongod.conf
```

#### サーバの初期設定
```
mongo
> use [DB名]
> db.addUser('[DBユーザ名]', '[DBパスワード]')
```

#### settings.pyのDB設定を変更
```python:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django_mongodb_engine', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': '[DB名]',                      # Or path to database file if using sqlite3.
        'USER': '[DBユーザ名]',                      # Not used with sqlite3.
        'PASSWORD': '[DBパスワード]',                  # Not used with sqlite3.
        'HOST': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': 27017,                      # Set to empty string for default. Not used with sqlite3.
    }
}
```

**USER,PASSWORDが設定されていると、`python manage.py test`でDBへのログインエラーが発生する。
そのため、開発環境ではUSER=''、PASSWORD=''にしておいた方が良さそう 。**

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

#### SITE_IDのエラーが出たら
MongoDBではIDがObjectIDでなければならないが、DjangoのSITE_IDはデフォルトで1になっているため、下記のようなエラーが発生する。

> bson.errors.InvalidId: AutoField (default primary key) values must be strings representing an ObjectId on MongoDB (got u'1' instead). Please make sure your SITE_ID contains a valid ObjectId string.

http://django-mongodb.org/troubleshooting.html#site-id-issues
では`python manage.py tellsiteid`でSITE_IDに設定するIDを取得してこいとなっているが、この時点ではdjango_siteにそもそもレコードがないので取ってこれない。

そのため、下記のようにして手動でサイトを作ってやればよい。

```
python manage.py shell

>>> from django.contrib.sites.models import Site
>>> s = Site()
>>> s.save()
>>> quit()

python manage.py tellsiteid
```

これで取ってきたSITE_ID をsettings.pyに設定する。

```python:settings.py
SITE_ID = u'XXXXXXXXXXXXXXXXX'
```

と思ったが、結局test時にこのエラーが出ることは押さえられなかった。

原因はdjango/contrib/sites/management.py。
ここでSite作成時に強制的にpk=1を入れているため。

```python:django/contrib/sites/management.py
def create_default_site(app, created_models, verbosity, db, **kwargs):
    # Only create the default sites in databases where Django created the table
    if Site in created_models and router.allow_syncdb(db, Site) :
        if verbosity >= 2:
            print "Creating example.com Site object"
        # The default settings set SITE_ID = 1, and some tests in Django's test
        # suite rely on this value. However, if database sequences are reused
        # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that
        # the next id will be 1, so we coerce it. See #15573 and #16353. This
        # can also crop up outside of tests - see #15346.
        s = Site(pk=1, domain="example.com", name="example.com")
        s.save(using=db)
    Site.objects.clear_cache()

signals.post_syncdb.connect(create_default_site, sender=site_app)
```

面倒なので、INSTALL_APPSでdjango.contrib.authとdjango.contrib.sitesを使うのをやめた。

```python:settings.py
INSTALLED_APPS = (
    #'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    #'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)
```