简体   繁体   中英

Use custom model manager for ManyToMany and OneToMany fields on DRF serializer

I have overridden the default model manager objects to only return objects for which is_deleted is no True.

+------+------------+
| Name | is_deleted |  
+------+------------+
| foo  | True       |  
| bar  | False      |  
| baz  | False      |  
+------+------------+

So, whenever I do MyModel.objects.all() gives me -

+------+------------+
| Name | is_deleted |  
+------+------------+
| bar  | False      |  
| baz  | False      |  
+------+------------+

But ManyToMany field is not respecting my objects manager. When I do user.foo_set.all() , I get all the objects, which I don't want. Is there a way around to do it?

I know that I can do user.foo_set(manager='objects').all() and it'll pick my object manager and give only the non deleted items but here's the problem -

I'm using Django Rest Framework and for serializing ToMany fields, it would give me all objects, regardless of their is_deleted value. Is there a way to enforce the object manager on the serializer for ToMany fields?

Right now, I'm using this, which seems kind of hack-ish -

class MySerializer(serializers.HyperlinkedModelSerializer):
    things = serializers.SerializerMethodField()

    class Meta:
        model = MyModel
        fields = ('id', 'things')

    def get_things(self, obj):
        return many_field_serialize(obj, 'things', ThingSerializer)





def many_field_serialize(obj, field_name, serializer_class):
    """
    Serializer, by default would give us all the related results, while we
    want to ignore the ones which have been marked as deleted or archived.
    We have our custom modele manager for that - `objects` but serializer
    doesn't use that. So the only solution at this time seems to manually
    get all the related fields and apply our `objects` model manager on it.

    There should be a better way to do it, or we'll keep duplicating this
    logic for every related field serializer.
    """
    items = getattr(obj, field_name)(manager='objects').all()
    serialized_items = serializer_class(
        instance=items, many=True
    )
    return serialized_items.data

Finally figured it out. All I had to do was make the objects model manager default (By defining it as the first manager in model), and in the model manager set use_for_related_fields = True , so that the related fields would use your base model manager by default.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM