2009-05-28 4 views
3

ここでは、ユーザーモデル(カスタムユーザー)を適切にサブクラス化したとします(http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/カスタムユーザークラスはdjangoでアプリケーションを中断しますか?

コメントアプリをインストールしました。

{{comment.user}} # which provides User, not my CustomUser 

と私はそれを回避するにはどうすればよいので、

{{comment.user.CustomProperty}} #does not work. 

:私が書くテンプレート内のコメントのユーザーにアクセスするための

答えて

2

comments.CommentからForeignKeyはそうcomment.userはあなたの親オブジェクト(:ベースUserモデルIE)を与える照会、内蔵のUserオブジェクトのをDjangoのことです。 Djangoの継承の弱点は、私はこれを考えるために起こる

{{ comment.user.customeruser.customproperty }} 

さ:

{{ comment.user.customeruser }} 

その後、あなたができるようになる。しかし、Djangoの継承は、スーパークラスからサブクラスのバージョンを取得する方法が提供されていPythonでオブジェクトの継承から期待される動作を正確に反映しているわけではありませんが、少なくとも回避策があります。私はほとんど右行動の私のバージョンでパッチを提出するアウト急いでないんだので、私はカール・マイヤーさんのコメントに同意


:-)文句を言うことはできません:それは自動的にせずにサブクラスを高価フェッチすることができ親モデルのdbテーブルを変更し、親クラスのクエリからサブクラスのインスタンスを返すことは、クエリセットがクエリセットが実行されたモデルを返すというDjangoの約束と矛盾します。

しかし、実際には、Djangoの継承は機会にいくつかの厄介な余分なステップにつながります。 Djangoを0.91から使用し、オブジェクト・リレーショナル・マッピングの問題を解決するためのさまざまな戦略がトレードオフになっていることを知ったので、現在Djangoで継承していて、現在の実装が優れていると感じています。私の元の答えがプロジェクトに対してわずかであると解釈されるのは嫌です。

このように、私はこの答えを、あなたがサブタイプがどのタイプであるのかわからない場合に、Carl自身が解決策に提供した答えにリンクするように編集すると考えました:How do I access the child classes of an object in Django without knowing the name of the child class?。彼はContentTypeフレームワークを使用するためのアドバイスを提供しています。いくつかのインダイレクションは関与していますが、ツールキットの良い一般化可能なオプションです。

+0

これは私が必要としていたものです。 – shanyu

+0

これは「Pythonでオブジェクトの継承から期待される動作を反映していません」ということは本当ですが、実装されているのは実際には良い理由があります。パッチを作成しようとした場合、 :-)私はあなたの望む動作がオブジェクトを自動的に "リーフ"サブクラスにすると仮定します。問題は、高価な複数のクエリが必要な大規模な継承ツリーの問題です。または、親モデルに型情報を格納する必要がありますが、親モデルを変更することで継承のための多くのユースケースが削除されます。 –

+0

質問のための良い追加情報、Carl。別の質問のContentTypesフレームワークに基づいて、あなたの回答の1つにリンクを追加しました。 –

1

あなたが言ったように、comment.userUserであり、CustomUserではないので、私はそこに道があるとは思わない。

http://docs.djangoproject.com/en/dev/topics/db/models/#proxy-modelsを参照してください:

クエリセットはSTILL
あなたはユーザーオブジェクトを照会するたびにDjangoのリターン、たとえば、MyUserとオブジェクトを持ってする方法はありませんが要求されたモデルを返します。 Userオブジェクトのquerysetは、これらのタイプのオブジェクトを返します。プロキシオブジェクトの全体のポイントは、元のユーザーに依存しているコードはそれらを使用し、独自のコードでは、(ほかのコードが頼りにしていない)拡張機能を使用できることです。ユーザー(または他の)モデルをどこにでも自分の創造物の何かに置き換える方法ではありません。

多分この場合、UserProfileを使用する古い方が良い選択でしょうか?

私はあまり役に立たない場合は申し訳ありません。

+0

私は古い古いuserprofileを使用しましたが、userprofileがそれ自体(友人のように)多対多の関係を持っていたときに、物事がうまくなりませんでした。これを見て、それは "素敵"ではないのですか?:friend = my_user.get_profile().after_users [0] .user - 結果として、私はUserをサブクラス化しました。しかし、今では、いくつかのアプリが私のために利用できなくなるようです。 – shanyu

+0

私は確かに非常に厄介なかなりすぐに得ることができる方法を見ることができます! – Arnaud

2

この記事のコメントからわかるように、それはまだ議論の余地がありますが、何が最善の方法なのですか。

サブクラス化してみましたが、多くの問題が発生しましたが、using profilesは完全に機能します。 IRCUserを作成

class IRCUser(models.Model): 
    user  = models.ForeignKey(User, unique=True) 
    name  = models.CharField(max_length=100, blank= True, null = True) 
    friends  = models.ManyToManyField("IRCUser", blank= True, null = True) 
    dataRecieved= models.BooleanField(default=False) 

は、次のように機能します。

>>> IRCUser(user = User.objects.get(username='Kermit')).save() 

EDITを:なぜuser_profilesはエレガントです:

我々はマルチとして動作しますWebアプリケーションを、書いている、のと仮定しましょうプロトコルチャット。ユーザーはICQ、MSN、Jabber、FaceBook、Googleトークなどのアカウントを提供できます.....

すべての追加情報を保持するカスタムユーザークラスを継承によって自由に作成できます。

class CustomUser(User): 
    irc_username = models.CharField(blank=True, null=True) 
    irc_password = models.PasswordField(blank=True, null=True) 
    msn_username = models.CharField(blank=True, null=True) 
    msn_password = models.PasswordField(blank=True, null=True) 
    fb_username = models.CharField(blank=True, null=True) 
    fb_password = models.PasswordField(blank=True, null=True) 
    gt_username = models.CharField(blank=True, null=True) 
    gt_password = models.PasswordField(blank=True, null=True) 
    .... 
    .... 

、これはより多くの1つのアカウントを持っているために、ゼロ値の多く

  • トリッキー何-のif-then検証
  • 不可能で

    • データ行につながります同じサービスで

    それでは、user_profilesでやりましょう

    class IRCProfile(models.Model): 
        user = models.ForeignKey(User, unique=True, related_name='ircprofile') 
        username = models.CharField() 
        password = models.PasswordField() 
    
    class MSNProfile(models.Model): 
        user = models.ForeignKey(User, unique=True, related_name='msnprofile') 
        username = models.CharField() 
        password = models.PasswordField() 
    
    class FBProfile(models.Model): 
        user = models.ForeignKey(User, unique=True, related_name='fbprofile') 
        username = models.CharField() 
        password = models.PasswordField() 
    

    結果:

    • はDBはゼロ値
    • によってフラッディングされていない必要なときに作成することができる
    • User_profiles
    • 同じタイプのNプロファイルは、一人のユーザ
    • に割り当てることができ
    • バリデーションは容易です

    この可能性がありますテンプレート内にもっと秘密の構文がありますが、views/template_tagsにいくつかのショートカットを付けたり、好きなように{% with ... %}を使用したりすることは自由です。

  • +0

    私がArnaudの投稿にコメントしたように、私はuserprofileが多対多の関係を持っていると嫌いです。ユーザーとユーザーの関係は、userprofileとuserprofileの関係になります。エレガントでないIMO。 – shanyu

    +0

    私の編集例を参照してください。なぜuser_profilesが*非常に*エレガントになるのでしょうか。 – vikingosegundo

    関連する問題