0

У меня есть следующие модели скелетов:Джанго Rest Serializer получить данные, связанные посредством внешних ключей

class A(models.Model): 
    post_id = models.ForeignKey('D') 
    user_id = models.ForeignKey('B') 

class B(AbstractBaseUser): 
    email = models.EmailField(unique=True) 
    username = models.CharField(max_length=20, unique=True)  
    first_name = models.CharField(max_length=40) 
    last_name = models.CharField(max_length=40) 
    # `resource_id` 
    profile_photo = models.ForeignKey('C', null=True) 

class C(models.Model): 
    user_id = models.ForeignKey('B') 
    name = models.CharField(max_length=60) 

Я хочу написать сериалайзер для А, который должен возвращать name от модели С, что связано с В.

связь здесь, как A-> B-> C Теперь, используя сериалайзер, я хочу, чтобы данные быть выбраны из C

Я хочу получить доступ C через канал а то есть получить profile_photo от B и получить имя пр ofile_photo от C

Я прокрутил через RelatedFields, как указано здесь Django Rest relations, но я не могу достичь того, что хочу.

Является ли их любым способом, я могу это достичь.

Также есть много полей, кроме упомянутых в скелете модели, и я не хочу их брать.

EDIT: Окончательный результат мне нужно, это все user_id для конкретного post_id от А с name от модели C

ответ

1

Вы можете сделать это с помощью ModelSerializer:

Примечание: Я будет asumme что 'posts.Post' является модель C

class CsSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = C 
     fields = ('name') 


class AsSerializer(serializers.ModelSerializer): 

    post_id = CsSerializer() 

    class Meta: 
     model = A 
     # exclude = ('field_you_dont_want_1', 'field_you_dont_want_2') 
     # fields = ('field_you_want_1', 'field_you_want_2') 

Обратите внимание, что в CsSerializer Вы можете вернуть любое поле из модели C в этом случае я просто возвращаю name.

Если вам просто нужна строка, вы можете использовать StringRelatedField

class AsSerializer(serializers.ModelSerializer): 
    post_id = serializers.StringRelatedField(many=True) 

    class Meta: 
     model = A 

Это StringRelatedField вернет то, что C вернуть модели в __unicode__ метод (метод __str__ если питон 3.x).

EDIT

Теперь из Вашего комментария, я знаю, что 'posts.Post' не C модель.Таким образом, вы могли бы использовать SerializerMethodField:

class AsSerializer(serializers.ModelSerializer): 
    c_name = serializers.SerializerMethodField() 

    def get_c_name(self, obj): 
     return obj.user_id.c_set.values('name') # this will return a list of dicts with B's related C objects. 

    class Meta: 
     model = A 

EDIT

Вы всегда можете определить методы класса в моделях:

class B(AbstractBaseUser): 
    email = models.EmailField(unique=True) 
    username = models.CharField(max_length=20, unique=True)  
    first_name = models.CharField(max_length=40) 
    last_name = models.CharField(max_length=40) 
    # `resource_id` 
    profile_photo = models.ForeignKey('C', null=True) 

    def get_profile_photo(self): 
     return self.profile_photo.name # This will return 'C' related object's name 

Так что, когда у вас есть объекты, такое а в:

a_object.user_id.get_profile_photo() 

Или если у вас есть объект B:

b_object.get_profile_photo() 

EDIT

Вы можете определить новый Serializer для класса C:

class CsSerializer(serializers.Serializer): 

    class Meta: 
     model = C 

Затем в AsSerializer

class AsSerializer(serializers.ModelSerializer): 
    c_name = serializers.SerializerMethodField() 

    def get_c_name(self, obj): 
     qs = obj.user_id.c_set.all() 
     qs_serialized = CsSerializer(qs, many=True) 
     return qs_serialized.data 

    class Meta: 
     model = A 
+0

К сожалению неясные, «posts.Post 'не является моделью C, это какая-то другая модель – ofnowhere

+0

@ofnowhereland So вам нужен доступ к C через B? – Gocht

+0

@ofnowhereland Я отредактировал ответ – Gocht