ラベル Django の投稿を表示しています。 すべての投稿を表示
ラベル Django の投稿を表示しています。 すべての投稿を表示

2016-02-25

django.db.utils.ProgrammingError: relation "auth_group" does not exist

Djangoで、manage.py test をしたら、
django.db.utils.ProgrammingError: relation "auth_group" does not exist
とかいうエラーになって困った。開発環境のmacの上では起こらないんだけど、Ubuntu Server14.04で起こる。データベースはPostgreSQL。

何だろうっていろいろ調べたけど、ここが答えをくれた。 次のように言ってる人がいた。
Did you run python manage.py makemigrations appname first, where "appname" is the name of the app containing your custom user model inheriting from AbstractUser?
AbstractUserを定義しているappnameを指定して、makemigrationsをしたら解決。モデルがちゃんとつくられていなかったみたい。そういえば、DBをflushした後、これを実行するの忘れてたかも。

migrationのテーブルに不完全なデータしかない状態で、テスト用のテーブルを作成しようとしてエラーになっていたということだろうか。

2016-02-17

DjangoでModelFormのカスタマイズ

DjangoでModelFormを使っていて、FormFieldを追加するとき。Modelのinstanceとの値のやりとりをどうしようか迷う。どうやら、初期値はModelFormの__init__()でモデルからフォームに渡してやり、フォームからモデルへの値の変更はModelFormの_post_save()でやるのが良さそう。

理解可能なように説明すると面倒くさいからできそうにない。

class ArticleForm(forms.ModelForm):
 
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.fields["text"].initial = self.instance.get_nice_text()
    
    def _post_clean(self):
        super()._post_clean()
        self.instance.set_nice_text(self.cleaned_data["text"])


という感じだといいのではないか。

2016-02-12

django-allauthを使ってTwitterアカウントでログイン

django-allauthを使って、Twitterアカウントでログインする機能を追加しようとしている。いくつか注意点。

django-allauth側の設定としては、settings.pyでの設定と、Webの管理画面でのDBの設定と二つやらないとダメ。管理画面では、social applicationsのとこでサイトIDを忘れずにと追加してあげないといけない。

Twitter側の設定としては、Callback URLを指定していないと、Twitterでログインする機能を利用できないでエラーになる。「Allow this application to be used to Sign in with Twitter」っていうのにチェックを入れていても、それだけじゃダメ。




ちなみに、Twitterにウェブアプリを登録しようとしたんだけど、現時点では日本語ドメインに対応していないみたい。punycodeでもダメ。不正はURLとして扱われる。

2016-02-11

Ubuntu14.04でDjangoを複数動かす

Apache2.4のVirtualHost、python3.4のvenv、mod_wsgiのdaemon mode、これらを使った。手順というよりも注意点を書き留めておく。

Ubuntu14.04では、python3のvenvが失敗するという情報があったけど、大丈夫だった。venv(もしくはpyvenv)は、「apt-get install python3.4-venv」でインストールしないといけない。
venvが失敗するというのは、ensurepipモジュールが欠けていて、pipがインストールされないとのことだった。その場合に、手動でpipをインストールすれば良いとかいう情報もあった(手動でpipをインストールした場合、apt-getからインストールしたpython3-psycopg2とかpython3-lxmlとかへのパスが通っているのかは謎)。しかし、問題なくvenvを実行できた。

仮想環境をつくるときは、pyvenvではなく、python3 -m venv を呼び出すクセをつけておいた方が良さそう。複数のバージョンのpython3が入っている場合に、どのpython3を使ってvenvを実行するのかで、仮想環境で使うpythonのバージョンを選択できるからだ。pyvenvだとこれができない。

とはいえ、mod_wsgiを動かすpythonのバージョンを細かく指定することは、たぶんできない。だから本番のサーバーではpyvenvを使おうがvenvを使おうが同じことだ。

仮想環境をつくるときは、「python3 -m venv --system-site-packages --symlinks 仮想環境ディレクトリへのパス」という具合にオプションを与えておくと、activateしたときに、mod_wsgiを動かすときに近い環境になるはず。--upgradeを付けとけば、失敗してもやり直せる。(--upgrade なしでもやり直せそう。あと、--symlinks はデフォルト値だから省略していい。)

activateするには、「source 仮想環境ディレクトリへのパス/bin/activate」。 activateした後でsudoすると、環境変数が上書きされてしまうのでやってはいけない。たとえば、activateした後で「sudo pip install django」とやると、デフォルトのpython2のsite-packagesにdjangoがインストールされてしまう。そうならないように「sudo -s」としてから、activateする。で「pip install django」とやれば、仮想環境のsite-packagesにインストールされる。



2016-02-05

ApacheのVirtualHostの設定で、ServerNameにもServerAliasにもヒットしない場合

ApacheのVirtualHostの設定で、ServerNameにもServerAliasにもヒットしない場合は、最初に設定されたVirtualHostが使われる。このことは公式ドキュメントにも書いてある。
リクエストが来ると、サーバはまず最初に <NameVirtualHost> にマッチする IP アドレスかどうかをチェックします。マッチすれば マッチした IP アドレスの <VirtualHost> のそれぞれのセクションの中から ServerName か ServerAlias に要求されたホスト名があるか探します。 見つかればそのサーバ用の設定を使います。マッチするバーチャルホストが見つからなければ、マッチした IP アドレスの リストの最初にあるバーチャルホスト が使われます。
 思ったように動いてくれないと思ったら、設定ミスってて
「見つからない場合は、リストの最初にバーチャルホストが使われる」っていうルルールが効いていた。

あと、複数のDjangoをVirtualHostを使って動かす場合は、mod_wsgiで、daemon modeってやつにしないといけない。これの設定がちょっと大変。

2015-09-04

submitボタンが2つある場合にどちらのボタンが押されたのか判定する

htmlのformに、submitボタンが2つある場合に、どちらのボタンが押されたのか判定するには、サーバー側でどうやればいいんだっけ?

<form>
    <input type="submit" name="btn1">
    <input type="submit" name="btn2">
</form>

みたいに、name属性をつけとけば、サーバー側(Djangoを使ってるとして)で、request.POST.get("btn1") の値が空かどうかで判定できる。

2013-08-23

TinyMCEエディタにマークアップした初期値を表示

TinyMCE4で、HTMLをエディタの初期値に表示する方法。下書き保存とかした内容を再編集するさいに必要になる。
こんな感じにやればいいっぽい。

<script type="text/javascript">
        tinymce.init({
            selector: "textarea",
         });
        tinymce.on("AddEditor", function(e) {
            tinyMCE.activeEditor.on("init", function(event) {
                tinyMCE.activeEditor.setContent("<h1>見出し</h1>テキスト");
            });
        });
    </script>

djangoで使おうと思って、プラグインを導入した方がいいのか迷ったんだけど、管理者サイトで使うのでなければテンプレートでJavaScriptを編集するの良さそう。

2013-08-17

User-Agentに漢字が混ざっててエラー

djangoだと、request.META.get("HTTP_USER_AGENT", "") ってやってUser-Agentを取得できる。django1.3.1を使っているんだけど、ユニコードではなくて、バイト文字列が返されるみたい。普通はASCII文字以外は含まれていないから問題ないんだけど、中国とかベトナムからのアクセスだと、User-Agentに漢字などが含まれているものがあって、それが原因でエラーになってた。
request.META.get("HTTP_USER_AGENT", "").decode("utf-8")
ってやればたぶん大丈夫。

こんなのがある。

Mozilla/5.0 (Linux; U; Android 4.2.1; zh-cn; W1+(MT6589/4核) Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30

Mozilla/5.0 (Linux; U; Android 4.1.2; vi-vn; IM-A830K Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Điện thoạiSafari/534.30

Mozilla/5.0 (Linux; U; Android 4.0.4; zh-cn; A10双核(8DM1) Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30

2013-07-05

MacPortsの後継としてHomebrewを導入してさらにgettextをインストール

ディスクの空きを増やしたくてMacPortsをアンインストールした。wineとか入れててやたらと重かったし、依存関係でごちゃごちゃしすぎてわけが分からなくなったので全部消してやった。でも、そしたらGNUのgettextが動かない。当たり前か。

Djangoで多言語対応をするためにはGNUのgettextが必要だ。そこで、MacPortsの代わりにHomebrewをインストールすることにした。MacPortsもHomebrew、パッケージ管理システムだが、Homebrewの方はMacにもともと入っているパッケージをなるべくつかうようにしているため、ビルドの時間やディスクの容量を節約できるという噂だ。

インストールのためには、Xcodeがインストールされていることが前提らしい。昔っからXcodeは入っているのでこれは問題なし。
あとは、ターミナルで
$ ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
と打ち込む。途中でパスワードを聞かれたから教えてあげた。
次のような出力があった。
$ ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
==> This script will install:
/usr/local/bin/brew
/usr/local/Library/...
/usr/local/share/man/man1/brew.1
==> The following directories will be made group writable:
/usr/local/.
/usr/local/bin
/usr/local/share
==> The following directories will have their group set to admin:
/usr/local/.
/usr/local/bin
/usr/local/share

Press ENTER to continue or any other key to abort
==> /usr/bin/sudo /bin/chmod g+rwx /usr/local/. /usr/local/bin /usr/local/share
Password:
==> /usr/bin/sudo /usr/bin/chgrp admin /usr/local/. /usr/local/bin /usr/local/share
==> Downloading and Installing Homebrew...
remote: Counting objects: 119077, done.
remote: Compressing objects: 100% (57206/57206), done.
remote: Total 119077 (delta 83061), reused 94319 (delta 60911)
Receiving objects: 100% (119077/119077), 18.97 MiB | 326 KiB/s, done.
Resolving deltas: 100% (83061/83061), done.
From https://github.com/mxcl/homebrew
* [new branch] master -> origin/master
HEAD is now at 4c74e09 fish: don't search extra folders for libiconv
==> Installation successful!
You should run `brew doctor' *before* you install anything.
Now type: brew help

最初に、ターミナルで「$ brew doctor」を実行しろって書いてある。やってみると次のような警告が出た。
Warning: /usr/bin occurs before /usr/local/bin
This means that system-provided programs will be used instead of those
provided by Homebrew. The following tools exist at both paths:
[省略]
Consider amending your PATH so that /usr/local/bin
occurs before /usr/bin in your PATH.
Homebrewもシステムと重複するプログラムとインストールすることもあるってことかな。とりあえず放ったらかし。

肝心なのは、gettextを入れること。インストールは「$ brew install なんちゃら」でいける。
$ brew install gettext
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/gettext-0.18.2.lion.bottle.tar.gz
######################################################################## 100.0%
==> Pouring gettext-0.18.2.lion.bottle.tar.gz
==> Caveats
This formula is keg-only: so it was not symlinked into /usr/local.

OS X provides the BSD gettext library and some software gets confused if both are in the library path.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

LDFLAGS: -L/usr/local/opt/gettext/lib
CPPFLAGS: -I/usr/local/opt/gettext/include

==> Summary
🍺 /usr/local/Cellar/gettext/0.18.2: 366 files, 11M

これでGNU gettextがインストールできた。しかし、「which gettext」とやっても何もでてこない。パスが通ってないからだ。
インストールのときの出力を見ると、OS XのBSD gettextと競合するかもしれないっていう配慮でパスを通していないようだ。こんな情報も見つけた。https://github.com/mxcl/homebrew/issues/8461

パスを通すには、「$ brew link --force gettext」とやる。いまは「--force」を忘れちゃダメみたい。

Djangoで静的ファイルを配信する

settings.pyの設定項目として、MEDIA_URL、MEDIA_ROOT、STATIC_URL、STATIC_ROOT、STATICFILES_DIRSなどがある。昔は、STATICなんちゃらという設定項目は存在しなかったと思う。しかし現在は、MEDIAなんちゃらはユーザがアップロードするファイルの保存と配信についての設定項目で、STATICなんちゃらは開発者があらかじめアップロードしておく静的ファイルの保存と配信のための設定という使い分けがされている。だから、MEDIAなんちゃらとSTATICなんちゃらを同じ値にしてはいけない。

さて、STATIC_URLは、静的ファイルをhttpで配信するときのURLの設定になる。templateのなかでは、{{STATIC_URL}} とやればその値を参照できる。たとえば、STATIC_URL='/static/'; という具合に設定する。

STATIC_URLを指定しても、実は、Djangoは静的ファイルの配信をまったくやってくれない。静的ファイルの配信はWebサーバーの仕事で、Djangoの仕事ではないから、というのがその理由だ。だから、ApacheならApacheを適切に設定してやらないといけない(Djangoの開発用サーバーを使っている場合については後述)。STATIC_URLは、Webサーバーの設定をやり易くしてくれるだけのものだ。

静的ファイル配信のためのWebサーバーの設定を簡単にするために大切なことは2つある。
ひとつは、URLが統一されていること(STATIC_URL)。
もうひとつは、配信する静的ファイルが同じディレクトリにまとめられていることだ。
どこにファイルをまとめることになるのかというと、STATIC_ROOTに設定したディレクトリの下だ。ファイルをまとめるにはツールをつかう。コンソールで「python manage.py collectstatic」を実行すれば、静的ファイルをいろんな場所から、STATIC_ROOTで指定した場所に集めてくれる。
すでに存在するファイルがあるときは、上書きしていいか「yes」か「no」で答えろと迫られる。処理を自動化したい場合は、「python manage.py collectstatic --noinput」としておけば黙って上書きしてくれる。

なんでcollectstaticするのかというと、アプリが複数個あったりプラグインを追加していたりして静的ファイルがいろんなところに散らばっているからだ。
では、collectstaticしたときに、どのディレクトリのファイルを集めてくるか?
ひとつは INSTALLED_APPSで指定したアプリのstaticディレクトリ。
あと、STATICFILES_DIRSに追加指定したディレクトリも対象となる。STATICFILES_DIRSには、タプルで複数の場所を登録できる。

Webサーバーの設定だが、Apacheの場合は、次のような感じだろう(仮に、STATIC_ROOT='/var/www/django/myproject/staticfiles/';とする)。
Alias /static/ /var/www/django/myproject/staticfiles/
<Directory /var/www/django/myproject/staticfiles>
    Order deny,allow
    Allow from all
</Directory>
Djangoの開発サーバーの場合は、urls.pyに、
from django.conf.urls.static import static
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
とやっておけば大丈夫だと思う。

2012-10-12

DjangoにDBのマイグレーションを行うプラグインを入れる

Djangoで manage.py syncdb をした場合、すでに存在するテーブルについては何も変更されません。models.pyをいじってスキーマを変更しても、それがDBに反映されません。
そこで、マイグレーションを行うプラグインの出番となります。どうもSouthが定番のようなので、これを入れます。

$ sudo pip install South

インストールに成功したら、settings.py を若干変更します。
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #自作のアプリ
    'south', #southをインストールする
    )
個人的な趣味としては、
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "south_migrations"))
SOUTH_MIGRATION_MODULES = {
    'myapp': 'migrations.myapp',
}
という具合にして、マイグレーションのときに生成されるファイルが、プロジェクトのディレクトリの外につくられるようにしておくのがいいと思います。その方が、ローカルのプロジェクトをサーバー上にあげるときに都合がいいからです。

settings.py の編集が終わったら、普通に、manage.py syncdb をします。これによって、southが利用するDBのテーブルがつくられます。SOUTH_MIGRATION_MODULESを明示的に指定した場合は、親となるモジュール(上記の例ではmigrations)が存在しないとエラーになるので、ここでつくっておきます。ここまでできたら、

$ python ./manage.py convert_to_south myapp

を実行します。これにより、既存のアプリをsouthで管理するように設定できます。今後、モデルに変更があった場合は、

$ python ./manage.py schemamigration myapp --auto
$ python ./manage.py migrate myapp

とやれば、たいていはsouthが何とかしてくれるはずです。

2012-10-06

CentOSにPostgreSQLをインストール

yumでインストールします。
$ sudo yum -y install postgresql-server
依存関係により、

  • postgresql-server
  • postgresql-libs
  • postgresql-server

の3つがインストールされることになります。現在はバージョンは、8.4.13-1.e16_3です。

これでインストールはできているのですが、データベースサーバーが起動していないので、まだ利用することはできません。最初の起動のため、次の2つコマンドを打ちます。
$ sudo service postgresql initdb
$ sudo service postgresql start
ここで、initdbをせずにpostgresqlを起動しようとすると、次のようなエラーになります。
/var/lib/pgsql/data is missing. Use "service postgresql initdb" to initialize the cluster first.
                                                           [失敗]

CentOSを再起動したときにpostgresqlも自動的に起動されるように設定しておきます。
$ sudo chkconfig postgresql on

これでデータベースサーバーの起動はOKです。後は、ユーザーの設定を行います。
PostgreSQLのインストールと同時にpostgresというユーザーがつくられるようです。
$ id postgres
uid=26(postgres) gid=26(postgres) 所属グループ=26(postgres)
このユーザー "postgres" にパスワードを設定します。
$ sudo passwd postgres
パスワードが設定できたら、ユーザーを変更します。デフォルトでは、Ident認証という方式で認証を行うため、CentOSのユーザーとPostgreSQLのユーザーが一致していないとエラーになるようです。
$ su - postgres
後は、createdbでデータベースを作成したり、 psqlで接続したりできます。

Ident認証ではなく、パスワード認証に変更したい場合は、postgresqlにユーザーを追加した後で、設定を変更します。
postgresユーザーでパスワード認証を行いたい場合は、次のようにしてパスワードを設定します。
ALTER  USER  postgres  WITH PASSWORD  'newpassword';
という具合です。postgresユーザーは最初から存在するのでALTER USERですが、新規ユーザーを追加するのであれば代わりに、CREATE USER文を使います。

パスワード認証を行うためには、DBの設定も変更する必要があります。設定ファイルなどは、たいてい「/var/lib/pgsql/data/」以下にあるようです。今回修正するのは、
/var/lib/pgsql/data/pg_hba.conf
というファイルです。「local    all    ident」という行をコメントアウトして「local    all    password」を追加します。
#local   all         all                               ident
local   all         all                               password
これでパスワードで認証することができます。たとえばユーザーがpostgresのときに、
psql  -U  postgres
とやれば、postgresユーザーで接続できます。


DjangoからPostgreSQLに接続する場合は、データベースの設定に、django.db.backends.postgresql_psycopg2を指定します。さらに次のコマンドで必要なモジュールをインストールしなくてはいけません。
$ sudo yum -y install python-psycopg2

2012-10-04

DjangoでImageFieldやFileFieldが空でないか調べる

たとえば、次のようなモデルがあったとします。
class MyModel(models.Model):
    thumbnail = ImageField(upload_to="path", null=True, blank=True)

ここで、ImageFieldにファイルがセットされているかどうか見分けて処理を切り替えたい場合の判定方法ですが、単に、
m = MyModel.objects.get(id=1)
if m.thumbnail:
    file_is_set() #ファイルあり
else:
    file_is_empty() #ファイルが空
という具合に判定すればOKなようです。

2012-04-03

djangoでcron

Bing Translateのアクセストークンを取得する処理に結構時間がかかるので、9分おきに自動でトークンが更新されるようにcronを設定することにしました。

まず、トークンを更新する処理をdjango-adminに追加します。名前を refresh_token とします。

そのあと、
sudo crontab -e -u root
という具合にして、root権限で実行される処理を定義するためのエディタを開いて、そこに次の記述を追加しました。

0-59/9 * * * * /path/to/manage.py refresh_token

これで9分おきに manage.py refresh_token が実行されるのですが、残念ながら上手く動きませんでした。カレントディレクトリが /root であるために、refresh_tokenが見えていないみたいです。

おそらく、cronを実行するときのディレクトリを変えるという手もあったのでしょうが、もう一個shellscriptを書いて、カレントディレクトリを変更してからmanage.py refresh_tokenを実行するようにしました。ShellScriptの中でsudoを使ったらエラーになって、ここでも若干手こずりましたが、無事に動作することを確認しました。実行するユーザーはrootでない方がいいかもしれませんが。

2012-03-14

Djangoの開発サーバーで静的ファイルを配信する

こんな感じにして、キャッシュを無効かするのがいいかと思います。

if settings.DEBUG:
    from django.views.static import serve as static_serve
    from django.views.decorators.cache import never_cache
    urlpatterns += patterns("",
        url(ur"^static/(?P.*)$", never_cache(static_serve), dict(document_root=settings.STATIC_ROOT)),
    )

と、思ったのですが、これでもキャッシュされてしまうようです。なぜだかよくわかりません。

2012-03-08

django-grappelliでレイアウトが崩れてしまう場合

djangoの管理コンソールのテーマをカッコ良くできるという触れ込みのdjango-grappelliを試してみたのですが、レイアウトが崩れてしまいました(FireFoxとChromeで確認)。一度は諦めかけたのですが、インストールガイドを再度読んでみたところ、INSTALLED_APPで'grappelli'を'django.contrib.admin'よりも先に読み込まなければいけないと書かれているのを読み落としていたことに気づきました。この部分を修正したら、ちゃんと表示されました。Django 1.3.1と、Grappelli 2.3.7 の組み合わせで確認しました。

しかし、選択中の項目がハイライトされないので、タブキーを使ってキーボードで操作するには不向きな管理画面になってしまうという問題点があります。

django-registrationの使い方

djangoでユーザー登録機能を簡単に追加できるプラグインdjango-registrationの使い方を調査中です。
pipからもインストールできますが、pipでインストールできる安定版バージョン0.7と、bitbucketでダウンロードできる0.8alpha-1とでは、だいぶ設定が異なるようです。

デフォルトでは次のように動作します。
  1. ユーザー名、メールアドレス、パスワードでユーザー登録情報が送信される
  2. Userオブジェクトが生成され(この状態ではis_activeがFalse)、ユーザーに確認メールが送信される。
  3. 確認メールの中のリンクがクリックされるとそのユーザーのis_activeがTrueとなってログインを行えるようになる

機能させるには、settings.pyの変更、DBの更新、urls.pyの変更、templateの作成の4つが必要です。

settings.py

INSTALLED_APPSに、"django.contrib.auth"、"django.contrib.sites"、"regstration"を記載します。
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.sites',
    'registration',
    # ...other installed applications...
)
ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window; you may, of course, use a different value.
ACCOUNT_ACTIVATION_DAYS は、確認メールの有効期間(日単位)です。

urls.py

'registration.backends.default.urls' をincludeします。bitbucketでダウンロードできる最新版のバージョン0.8では次のようにします。
urlpatterns += patterns('',
    (r'^accounts/', include('registration.backends.default.urls')),
)
pipでインストールされるバージョン0.7では、'registration.backends.default.urls' ではなく 'registration.urls' としなければなりません。バージョン0.8で 'registration.urls' をincludeした場合は警告は出ますが一応動作はすると思います。

tempates

templateを作成するのはめんどうなので、手っ取り早く動作させたい場合は、以下でダウンロードできるテンプレートのどれかを使うと良さそうです。(ただし、バージョンごとテンプレートの使用が異なるようなので、正常に動作しない可能性が高いです。)
https://github.com/dokterbob/django-registration-templates (古い?)
https://github.com/banterability/django-registration-templates (使用可能な変数がコメントアウトして書かれているだけ)
https://github.com/yourcelf/django-registration-defaults (未確認)
https://bitbucket.org/cliff/django-registration-templates (未確認)

登録するユーザー情報が、ユーザー名とメルアドとパスワードだけでは足りないという場合は、UserProfileを使います。

2012-03-07

Djangoで開発サーバーのみDEBUG=Trueとなるように設定

settings.pyで行うDjangoのデバッグ設定ですが、開発サーバーでのみDEBUG=Trueで本番サーバーやテストサーバーではFalseになるようにしておくのがいいと思います。手動で値を書き換えていると、DEBUG=Trueのまま本番サーバーにアップロードしてしまうリスクがありますが、次のような設定しておけば安心です。「/myname/」の部分には、開発しているソースコードのパスには含まれるが本番サーバーやテストサーバー上のパスには含まれない文字列を指定します。
import os
PROJECT_DIR = os.path.abspath(os.path.dirname(__file__))
DEBUG = "/myname/" in PROJECT_DIR
TEMPLATE_DEBUG = DEBUG

開発サーバーで静的ファイルの配信を行う場合、DEBUG=Trueでないといけなかったりするので、DEBUG変数の設定は重要です。

2011-11-09

CentOS5にmemcachedをインストールする

どうやら昔はyumでmemcachedをインストールできたみたいだが、いまはrpmforgeを追加してもmemcacheが見つからない。そこで、次のようにしてCentOS5にmemcachedをインストールした。

# yum -y install libevent-devel
# wget http://memcached.googlecode.com/files/memcached-1.4.9.tar.gz
# tar -zxvf memcached-1.4.9.tar.gz
# cd memcached-1.4.9
# ./configure
# make
# make install

なぜだか知らないが、wget http://memcached.org/latest でソースをダウンロードした場合は上手くmakeできなかった。

起動時にmemcachedが自動で起動されるように次の設定もした。

# vi /etc/rc.d/init.d/memcached
=====ここからviで追加=====
#!/bin/bash
#
# memcached
#
# chkconfig: 345 80 20
# description: memcached

TARGET=memcached
DST_BIN=/usr/local/bin/${TARGET}
EXEC_USER=apache
CACHE_SIZE=64

start()
{
  echo -n "Starting ${TARGET}: "
  ${DST_BIN} -d -u ${EXEC_USER} -m ${CACHE_SIZE}
  echo
}

stop()
{
  echo -n "Shutting down ${TARGET}: "
  killall ${TARGET}
  echo
}

case "$1" in
  start)
    start
    ;;

  stop)
    stop
    ;;

  restart)
    stop
    start
    ;;

  *)
    echo "Usage: `basename $0` {start|stop|restart}" >&2
    exit 1
esac

exit 0
=====ここまで=====
# chmod 755 /etc/rc.d/init.d/memcached
# chkconfig --add memcached
# chkconfig memcached on
# service memcached start

今回の目的は、Djangoでcacheを利用することだったので、yumで、python-memcachedのインストールも行った。

# yum -y install python-memcached

2011-10-24

Django1.3の管理サイトが便利すぎる



Djangoの管理コンソールは昔から便利だと思っていたが、久しぶりに最新版の1.3.1を試してみたら、管理コンソールが進化してものすごく便利になっていた。

とくに、ユーザが自分で生成したオブジェクトだけを表示・編集できるようになったことはすばらしい。
バージョン1.3がリリースされてから、かなり時間が経つが、ドキュメントが日本語化されていないようなので、このことを知らない人もいるかもしれない。
以前の管理コンソールは、すべてのオブジェクトにアクセス可能なサイト運営者用にしか使えない印象だったが、いまはサイトにユーザ登録した利用者用にも使えそうだ。

ユーザが生成したオジェクトのみを管理サイトでアクセス可能にするには、django.contrib.admin.ModelAdminを継承してたクラスを定義して、queryset、has_add_permission、has_change_permission、has_delete_permissionなどをオーバーライドする。querysetをオーバーライドするだけで、表示を絞り込むことはできるが、has_add_permissionなどで権限を正しく設定しておかないといけない。
ドロップダウンリストなどに他のユーザのオブジェクトが表示されてしまうのを直したい場合は、さらに、formfield_for_foreignkeyなどをオーバーライドすればよい。

Djangoの管理サイトは、以前よりもさらに便利で強力になった。しかし、もちろんすべてのニーズを満たすというわけではない。
たとえば、list_filterで絞り込みを設定した場合にも、他のユーザのオブジェクトが表示されてしまうのだが、これを防ぐ簡単な手立てはどうやらなさそうだ。
また、DBのテーブルを列挙するページ構成は、ユーザにとって使い勝手が悪い場合が多そうだ。ページ構成は、オブジェクトの階層構造に対応していることが望ましいと思うのだが、これを実現するには割りと大掛かりなカスタマイズが必要になると思われる。