【モデル作成】Django 初心者がコミュニティサイト的な何かにチャレンジしてみる
コレまでの履歴
三回目、データベースモデルを作ってみる。
その前に、先ず使いやすいテキストエディタ探しておこう。
知り合い内とかで聞く名前はこんな感じだった。IDE が混じってるけど気にしてはいけない。
- PyDev
- PyScripter
- Intype
- KomodoEdit(俺が愛用)
何故ここで勧めるかって?あったほうが楽できるから。
因みにこのBlogでスクリーンショット取るときはKomodoEditなのであしからず。
先ずは、アプリケーションを宣言する
先ずはアプリケーションを宣言してみる。
土台だけではどうし様もないしね、、、。
ということで、コンソールでアプリケーションを宣言してみる。
コマンドはこんな感じ
manage.py startapp community
コミュニティという名前のアプリケーションを開始すると。
間違えてしまった場合は、作成されたディレクトリ以下を削除すればOK!
community ディレクトリの中身は以下の通り。
- __init__.py 初期化ファイル(特に使わない)
- models.py モデルファイル(ここに DB 定義とか書いておく)
- tests.py テストコード(ユニットテスト用にしか見えない)
- views.py ビューコード(Django の View はコントローラ的な、、、)
tests.py はインストールのとき、「django-command-extensions」を入れた影響かな?(デフォルトだと無かった気がする)
モデルを作ってみる
で、モデルを作成してみる。
Symfony(PHP)なら、yml 編集してコンソールコマンド。RubyOnRails(Ruby)ならコンソールでコマンド一発。
Django の場合は、モデルを書く。(RubyOnRails では、モデルクラスと、DB適用用のマイグレートクラスの二つがあるが、Django はモデルだけ書けばそれをマイグレートクラスとしても適用できる。そういう意味では分かりやすくてよいと思った。)
models.py がそれに当たる。
先ず、デフォであるものは何かと考えてみると、前回の admin 見ればいい。
- 姓
- 名
- 権限
- メールアドレス
これは元々ある、、、ということで、コミュニティサイトで他に足りないものを考える。
- フレンド登録
- ニックネーム
- ホームページ
- 趣味
- 特技
- 都道府県
挙げるとキリがないか、、、、ともすれば、必須っぽいもの意外は、後から質問追加できる形がいいのかなー。
保存するのはRDBだから勝手に拡張とかやりにくいコト考えて、切り離せるものは切り離す。
「フレンド登録」はユーザ間を繋げるデータなので、ユーザ情報にくっつけれないみたいな考え方しとく。
まぁ独断と偏見でこんなものを指定しとく。
- ニックネーム
- ホームページ
ホームページは何か違うんじゃね?と思う人もいると思うけど、俺が欲しいw
ということでこんなモデルを作ってみる。
# coding:utf-8 from django.db import models from django.contrib import admin from django.contrib.auth.models import User class UserProfile(models.Model): nick_name = models.TextField(unique=True,max_length=64) home_page = models.URLField(verify_exists=False,null=True,blank=True) admin.site.register(UserProfile) # admin 管理サイトに登録
して、どうやってユーザテーブルと紐付けしようかと悩んだら、コレ。
http://djangoproject.jp/doc/ja/1.0/topics/auth.html?highlight=auth#storing-additional-information-about-users
公式ドキュメントがしっかりしてるのはいいことね。
ということで以下のように変更。
# coding:utf-8 from django.db import models from django.contrib import admin from django.contrib.auth.models import User class UserProfile(models.Model): target_user = models.ForeignKey(User,unique=True) nick_name = models.TextField(unique=True,max_length=64) home_page = models.URLField(verify_exists=False,null=True,blank=True) admin.site.register(UserProfile)
そして、多分 settings.py あたりだろうか?
AUTH_PROFILE_MODULE をセットする。ついでに、アプリケーションの登録もしておこう。
AUTH_PROFILE_MODULE = 'community.userprofile' INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'community', )
他に、必要なので特殊なのはフレンドリンクだろうか?
ForeignKey の使い方はさっきのを参照してやってみる。
# coding:utf-8 from django.db import models from django.contrib import admin from django.contrib.auth.models import User class UserProfile(models.Model): target_user = models.ForeignKey(User,unique=True) nick_name = models.TextField(unique=True,max_length=64) home_page = models.URLField(verify_exists=False,null=True,blank=True) class UserLink(models.Model): target1 = models.ForeignKey(User,unique=False) target2 = models.ForeignKey(User,unique=False) admin.site.register(UserProfile) admin.site.register(UserLink)
この辺で不安なので「manage.py syncdb」をかけてみる(この操作でDBに適用する)。
すると、二つほどエラーが出た。
Error: One or more models did not validate: community.userlink: Accessor for field 'target1' clashes with related field 'Use r.userlink_set'. Add a related_name argument to the definition for 'target1'. community.userlink: Accessor for field 'target2' clashes with related field 'Use r.userlink_set'. Add a related_name argument to the definition for 'target2'.
関係がクラッシュするから related_name を設定しなさいとのこと。
# coding:utf-8 from django.db import models from django.contrib import admin from django.contrib.auth.models import User class UserProfile(models.Model): target_user = models.ForeignKey(User,unique=True) nick_name = models.TextField(unique=True,max_length=64) home_page = models.URLField(verify_exists=False,null=True,blank=True) class UserLink(models.Model): target1 = models.ForeignKey(User,unique=False,related_name='target1') target2 = models.ForeignKey(User,unique=False,related_name='target2') admin.site.register(UserProfile) admin.site.register(UserLink)
これで問題なく通った。
最後に、SNS 的な質問と、その結果の記録フィールドでも用意してみようと思った。
以下の感じ
- ProfileSubset : 質問と、質問の序列、入力タイプ
- ProfileSubsetValues : ProfileSubset が選択型だった場合の選択肢
- UserProfileSubset : ユーザと質問(およびその解答)の紐付け
結果コードはこんな感じ?
# coding:utf-8 from django.db import models from django.contrib import admin from django.contrib.auth.models import User class UserProfile(models.Model): target_user = models.ForeignKey(User,unique=True) nick_name = models.TextField(unique=True,max_length=64) home_page = models.URLField(verify_exists=False,null=True,blank=True) def __unicode__(self): return self.nick_name class UserLink(models.Model): target1 = models.ForeignKey(User,unique=False,related_name='target1') target2 = models.ForeignKey(User,unique=False,related_name='target2') def __unicode__(self): return self.target1.name + ' to ' + self.target2.name # Question and question type class ProfileSubset(models.Model): # Profile view name name = models.TextField(unique=True,null=False,max_length=32) # profile data type(text:0 , radio:1 , chexkbox:2 , intval:3) type = models.IntegerField(null=False) # Question Rank rank = models.IntegerField(null=False) def __unicode__(self): return self.name # UserProfile Type extend values # raido , checkbox class ProfileSubsetValues(models.Model): # Profile subset parent = models.ForeignKey(ProfileSubset) # subset value value = models.TextField(max_length=32) def __unicode__(self): return self.parent.name + " : " + self.value # User inform class UserProfileSubset(models.Model): # taeget user user = models.ForeignKey(User) # target subset subset = models.ForeignKey(ProfileSubset) # subset value value = models.TextField(max_length=255) def __unicode__(self): return str(self.user) + " : " + self.subset.name + "=" + self.value admin.site.register(UserProfile) admin.site.register(UserLink) admin.site.register(ProfileSubset) admin.site.register(ProfileSubsetValues) admin.site.register(UserProfileSubset)