2016-04-09 1 views
0

すべてのカスタム関連マネージャ/ wの逆外部キーフィールドをシリアル化。私は逆のフィールドでカスタム関連のマネージャを使用しています。私は、外部キーを介して一緒に結合され2つのモデルを持っている</p> <p>、Djangoの残りのフレームワーク

models.py:

class Foo(models.Model): 
    name = models.CharField(max_length=23) 
    bar = models.ForeignKey("Bar", related_name="foos") 

class Bar(models.Model): 
    name = models.CharField(max_length=42) 
    my_custom_manager = MyCustomManager() 

class MyCustomManager(models.Manager): 
    use_for_related_fields = True 

    def get_queryset(self): 
    if self.instance.is_special(): 
     return do_something_special() # returns a list of Foos 
    return super(MyCustomManager, self).get_queryset() 

私は、次のコードを使用し、これを使用するには:

my_bar_instance.foos.add(my_foo_instance) 
my_bar_instance.foos(manager="my_custom_manager").all() 

を、私は、これは不自然な例であることを知っているが、時々私がする必要があることを私を信頼このフィールドにオブジェクトを追加するときに非標準のものを実行します。とにかく、このコードは正常に動作します。問題は、シリアル化しようとするときです。

serializers.py:

class FoosField(serializers.RelatedField): 

    queryset = Foo.objects.all() 

    list_serializer_class = ListSerializer 

    def to_representation(self, value):   
     if not value: 
      return {} 

     from .some_other_package import FooSerializer 
     serializezr = FooSerializer() 
     representation = serializezr.to_representation(value) 
     return representation 

    def to_internal_value(self, data): 
     if not data: 
      return None 

     from .some_other_package import FooSerializer 
     serializer = FooSerializer() 
     internal_value = serializer.to_internal_value(data) 
     return internal_value 

class BarSerializer(ModelSerializer): 

    class Meta: 
     model = Bar 
     fields = (
      'id', 
      'name', 
      'foos', 
     ) 

    foos = BarField(many=True, required=False, allow_null=True, queryset=Foo.objects.all()) 

それはちょうど "FOOS" フィールドの空のリストをoutputingされます。カスタムマネージャーfoos(manager="my_custom_manager")を指定するのではなく、リバースリレーションシップフィールドfoosを直接呼び出しているためです。 Django Rest Frameworkにカスタムマネージャを使用する方法を教えてください。

ありがとうございました

+1

私は完全に限りシリアライザが行くよう....カスタムマネージャで、ここでやっているのか理解しなかったが - あなたのためにこの仕事をしますか? 'FOOS = BarField(真=多く、必要= Falseを、ALLOW_NULL = Trueの場合、クエリセット= Bar.my_custom_manager.all())あなたは何とかDRFがオブジェクトから値を取得する方法を上書きする必要があるとしている' – zEro

+0

。それのための方法があるべきです、私は私の頭の上からそれを知らない。 –

+0

@zEro - それは素晴らしい提案です。残念ながら、それは動作しません。 – trubliphone

答えて

0

できます。しかし、それは醜いです:

serializers.py:私は1つの新しいクラス(FoosChildField)と2つの新しいメソッド(__init__ & many_init)を追加しました

class FoosChildField(ManyRelatedField): 

    def get_attribute(self, instance): 
    manager = self.child_relation.manager 
    if manager: 
     relationship = getattr(instance, manager.get_name()) 
     return relationship.all() if (hasattr(relationship, 'all')) else relationship 
    super(FoosChildField, self).get_attribute(instance) 

class FoosField(serializers.RelatedField): 

    queryset = Foo.objects.all() 

    list_serializer_class = ListSerializer 

    def __init__(self, **kwargs): 
     manager = kwargs.pop("manager", None) 
     super(FoosField, self).__init__(**kwargs) 
     self.manager = manager 

    @classmethod 
    def many_init(cls, *args, **kwargs):   
     list_kwargs = {'child_relation': cls(*args, **kwargs)} 
     for key in kwargs.keys(): 
     if key in MANY_RELATION_KWARGS: 
      list_kwargs[key] = kwargs[key] 
     return FoosChildField(**list_kwargs) 

    def to_representation(self, value):   
     if not value: 
      return {} 

     from .some_other_package import FooSerializer 
     serializezr = FooSerializer() 
     representation = serializezr.to_representation(value) 
     return representation 

    def to_internal_value(self, data): 
     if not data: 
      return None 

     from .some_other_package import FooSerializer 
     serializer = FooSerializer() 
     internal_value = serializer.to_internal_value(data) 
     return internal_value 

class BarSerializer(ModelSerializer): 

    class Meta: 
     model = Bar 
     fields = (
      'id', 
      'name', 
      'foos', 
     ) 

    foos = BarField(many=True, required=False, allow_null=True, queryset=Foo.objects.all(), manager=Bar.my_custom_manager) 

基本的には、マネージャをDRF関連のフィールドインスタンスに渡し、DRF関連のフィールドインスタンスをDRFの「子」フィールドに渡します(これはリストシリアライザなので)。 get_attribute fnはそのマネージャを使用して実際の値を取得します。

ヤック。

関連する問題