2017-06-03 20 views
0

私は会社を持つアプリケーションを持っていますが、この会社は0か複数のアドレスを持つことができます。企業はアドレスを持つことができる唯一の「モデル」ではありません。これを達成するために、私はContentTypesを使用します。Django Rest Framework:ContentTypeでネストされたシリアライズを行う方法

models.py

class Company(models.Model): 
''' models a company in the system. ''' 

    number = models.CharField(_('Number'), unique=True, max_length=20) 
    name = models.CharField(_('Name'), max_length=100) 
    active = models.BooleanField(_('Active'), default=True) 

    def _get_addresses(self): 
     ''' 
     ''' 
     contentType = ContentType.objects.get(
      model=self.__class__.__name__.lower() 
     ) 
     try: 
      addresses = Address.objects.get(
       actor_type=contentType, actor_id=self.id 
      ) 
     except Address.DoesNotExist: 
      addresses = [] 
     return addresses 
    addresses = property(_get_addresses) 

class Address(Auditable): 
    ''' models an address ''' 

    actor_type = models.ForeignKey(ContentType) 
    actor_id = models.PositiveIntegerField() 
    actor_object = fields.GenericForeignKey('actor_type', 'actor_id') 
    _type = models.CharField(
     _('Address Type'), 
     max_length=10, 
     choices=sorted(TYPES.items()) 
    ) 
    active = models.BooleanField(default=True) 
    address1 = models.CharField(_('Address 1'), max_length=50) 
    address2 = models.CharField(
     _('Address 2'), 
     max_length=50, 
... 

このように、私はまた、Profileモデルを持っている可能性があり、私はプロファイルに複数のアドレスをリンクすることができます。しかし、シリアライザを実装しようとすると、私の問題が発生します。

Serializers.py

class AddressSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Address 
     fields = (
      '_type', 
      'address1', 
      'address2', 
      'address3', 
      'country', 
      'state', 
      'city' 
     ) 

class CompanySerializer(serializers.ModelSerializer): 

    addresses = AddressSerializer(required=False, many=True) 

    class Meta: 
     model = Company 
     fields = (
      'number', 
      'name', 
      'addresses' 
     ) 

この実装は、私にこのerrorを与えます。それはアドレスモデル(それは理にかなっています)を反復することはできないと言いますが、自分のアドレスを反復可能にする方法がわかりません。

私は、会社だけでなく、ネストされた住所でもCRUD操作を実行する必要があります。

これについてのご意見はありますか?

+1

、そこにある、ことができますか? – zaidfazil

+0

@FazilZaid 'Company'から' Address'への関係はありません( 'addresses'プロパティを除いて、models.pyに追加したばかりです)、' Address'から 'Company'への関係を得ることができます。他のモデルに – m4rk4l

+0

しかし、一般的な外部キーは、シリアル化を行うためのフィールドとしてアクセスできません... – zaidfazil

答えて

1

次のデータベーススキーマは、一般的なシナリオに対する単なる提案です。

class Details(models.Model): 
    official_name = models.CharField(....) 
    is_company = models.BooleanField(default=False) 
    #something like that.... 

class Address(models.Model): 
    owner = models.ForeignKey(Details, related_name='addresses') 
    is_company = models.BooleanField(default=False) 
    building_name = ..... 
    building_no = ...... 
    locality = ...... 
    #some other fields..... 

class Company(models.Model): 
    details = models.OneToOneField(Details, related_name='company') 
    name = models.CharField(...) 
    number = ..... 
    is_active = ........ 

class Profile(models.Model): 
    details = models.OneToOneField(Details, related_name='profile') 
    name = models.CharField(....) 
    ......... 

ここで、各CompanyテーブルとProfileテーブルは、Detailsテーブルと1対1の関係にあります。詳細テーブルは、外部キーを含むアドレステーブルに関連しています。したがって、各会社またはプロファイルは、詳細テーブルを介して複数のアドレスを持つことができます。

ので、クエリはテーブルがために、それらの各フィールドが含まれているとして、逆クエリについては

company.details.addresses.all()#or 
profile.details.addresses.all() 

は簡単です、会社またはプロファイルインスタンスからのアドレスにアクセスするための

、のようになります所有者が与えられたアドレス、address.owner.profileまたはaddress.owner.companyであり、これはそれぞれのテーブルのフラグによって決定することができる。

私が知っているように、このようなデータベースを設計するのはやや疲れます。しかし、これはデータのより良いフォーマットへのシリアル化に役立ちます。次のように

シリアライザは

会社とアドレスの間には直接の関係はありません
class DetailsSerializer(ModelSerializer): 
    addresses = AddressSerializer(source='addresses', many=True) 
    class Meta: 
     model = Details 
     fields = ('addresses',) 

class AddressSerializer(ModelSerializer): 
    class Meta: 
     model = Address 
     fields = '__all__' 

class CompanySerializer(ModelSerializer): 
    details = DetailsSerializer() 
    class Meta: 
     model = Company 
     fields = ('details', .........) 

class ProfileSerializer(ModelSerializer): 
    details = DetailsSerializer() 
    class Meta: 
     model = Profile 
     fields = ('details', .........) 
+0

興味深いことに、私はあなたのソリューションを実装しようとします。コンテンツタイプでこれを行うことができない/できない理由がありますか?私はシリアライゼーションが必要です...もし良い提案がないなら、私は答えとしてこれを選ぶことになります – m4rk4l

関連する問題