27

最初に、私は次のようにUserProfileを開始しました。

from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    verified = models.BooleanField()
    mobile = models.CharField(max_length=32)

    def __unicode__(self):
        return self.user.email

AUTH_PROFILE_MODULE = 'accounts.UserProfile'で設定するとうまく機能しsettings.pyます。

ただし、私のWebサイトには、個人と企業の2種類のユーザーがいて、それぞれに固有の属性があります。たとえば、個人ユーザーには単一のユーザーのみを持たせ、したがって、を持たせuser = models.OneToOneField(User)、企業の場合は、同じプロファイルに関連する複数のユーザーを持たせたいので、user = models.ForeignKey(User)代わりにそうします。

そこで、モデルを2つの異なるモデルに分離することを考えましたIndivProfile。どちらも、モデル固有の属性を関連するサブモデルに移動しながらCorpProfile継承します。UserProfile私には良いアイデアのようで、おそらくうまくいくでしょうが、AUTH_PROFILE_MODULEユーザーごとに異なる2つのユーザープロファイルがあるため、この方法を指定することはできません。

UserProfileまた、複数のクラス(モデル)から継承して、次のようにすることも考えました。

class UserProfile(IndivProfile, CorpProfile):
    # some field

    def __unicode__(self):
        return self.user.email

このようにして、私はAUTH_PROFILE_MODULE = 'accounts.UserProfile'その問題を設定して解決します。しかし、Pythonの継承は左から右に機能し、のすべての変数IndivProfileが支配的になるため、これは機能するようには見えません。

IndivProfile確かに、変数をすべて一緒に混合した単一のモデルを常に持つことができCorpProfile、必要に応じて必要なモデルを使用します。しかし、それは私にはきれいに見えません。むしろ、それらを分離して、適切な場所で適切なモデルを使用することを望みます。

これを行うためのクリーンな方法の提案はありますか?

4

3 に答える 3

25

これは次の方法で実行できます。両方のプロファイルで必要な共通のフィールドを含むプロファイルを用意します。そして、あなたはすでにクラスを作成することによってこれを行っていますUserProfile

class UserProfile(models.Model):
    user = models.ForeignKey(User)
    # Some common fields here, which are shared among both corporate and individual profiles

class CorporateUser(models.Model):
    profile = models.ForeignKey(UserProfile)
    # Corporate fields here

    class Meta:
        db_table = 'corporate_user'

class IndividualUser(models.Model):
    profile = models.ForeignKey(UserProfile)
    # Individual user fields here

   class Meta:
        db_table = 'individual_user'

ここにはロケット科学は含まれていません。企業プロフィールと個人プロフィールを区別するキーワードを持っているだけです。たとえば、ユーザーがサインアップしていると考えてください。次に、ユーザーが企業にサインアップしているかどうかを区別するフィールドをフォームに用意します。そして、そのキーワード(リクエストパラメータ)を使用して、ユーザーをそれぞれのモデルに保存します。

その後、ユーザーのプロファイルが企業または個人であることを確認したい場合は、小さな関数を作成して確認できます。

def is_corporate_profile(profile):
    try:
        profile.corporate_user
        return True
    except CorporateUser.DoesNotExist:
        return False

# If there is no corporate profile is associated with main profile then it will raise `DoesNotExist` exception and it means its individual profile
# You can use this function as a template function also to use in template
{% if profile|is_corporate_profile %}

これがあなたをどこかに導くことを願っています。ありがとう!

于 2012-03-11T19:35:43.837 に答える
9

私はそれをこのようにしました。

PROFILE_TYPES = (
    (u'INDV', 'Individual'),
    (u'CORP', 'Corporate'),
)

# used just to define the relation between User and Profile
class UserProfile(models.Model):
    user = models.ForeignKey(User)
    profile = models.ForeignKey('Profile')
    type = models.CharField(choices=PROFILE_TYPES, max_length=16)

# common fields reside here
class Profile(models.Model):
    verified = models.BooleanField(default=False)

User結局、Djangoですでに定義されている2つの抽象モデルと私のモデルの間の関係を反映するために中間テーブルを使用することになりましたProfile。共通ではない属性がある場合は、新しいモデルを作成してに関連付けますProfile

于 2012-03-17T11:05:11.077 に答える
-1

スルーフィールドを使用してみる価値があるかもしれません。その背後にある考え方は、CorpProfileまたはIndivProfileモデルのスルーモデルとしてUserProfileモデルを使用することです。このようにして、CorpまたはIndivプロファイルがユーザーにリンクされるとすぐに作成されます。

from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.ForeignKey(User)
    profile = models.ForeignKey(Profile, related_name='special_profile')

class Profile(models.Model):
    common_property=something

class CorpProfile(Profile):
    user=models.ForeignKey(User, through=UserProfile)
    corp_property1=someproperty1
    corp_property2=someproperty2

class IndivProfile(Profile):
    user=models.ForeignKey(User, through=UserProfile, unique=true)
    indiv_property1=something
    indiv_property2=something

そうすれば、を設定できるはずだと思いますAUTH_PROFILE_MODULE = 'accounts.UserProfile'。実際のユーザーにリンクされているCorpProfileまたはIndivProfileを作成するたびに、一意のUserProfileモデルが作成されます。その後、dbクエリまたは必要なものを使用してそれにアクセスできます。

私はこれをテストしていないので、保証はありません。少しハッキーかもしれませんが、反対側では、このアイデアは非常に魅力的だと思います。:)

于 2012-03-11T16:59:13.037 に答える