2017-06-03 45 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。它說它不能遍歷Address模型(這是有道理的),但我不知道如何讓我的地址迭代。

我不僅需要對公司進行CRUD操作,還需要對嵌套地址es執行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.details.addresses.all()#or 
profile.details.addresses.all() 

對於反向查詢是簡單的表包含在它們各自的字段,用於給定地址的所有者將是address.owner.profileaddress.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

相關問題