django-rest-framework icon indicating copy to clipboard operation
django-rest-framework copied to clipboard

Re-prefetch related objects after updating

Open yuekui opened this issue 3 years ago • 5 comments

Instead of re-loading get_object() or not using any prefetch after updating, we could keep the instance and re-prefetch related objects for the updated instance.

refs: https://github.com/encode/django-rest-framework/pull/4553 https://github.com/encode/django-rest-framework/pull/4668 https://github.com/encode/django-rest-framework/issues/4661

yuekui avatar Jun 19 '21 05:06 yuekui

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 24 '22 13:04 stale[bot]

TLDR; this PR seems to be a good compromise between re-invoking get_object() and full (buggy, see below) invalidation of prefetched objects' cache during updates. @kevin-brown is it going to be merged?

So, about the bug.

Let we have a viewset with the following get_queryset():

def get_queryset(self):
     return Entity.objects.prefetch_related(
        Prefetch(
            "related_objects", 
            queryset=RelatedObject.objects.filter(is_removed=False).order_by("order")
        )
    )

Expected:

  • basically there shouldn't be differences between result of PATCH/PUT and repeated GET. In particular, GET /enitities/{pk}/ and PATCH /entities/{pk}/ {} should return the same object.

Actual:

  • if we use GET (list or retrieve), the prefetched objects will be in expected order and state. But if we use PATCH/PUT, the UpdateModelMixin's invalidation breaks both things and uses just instance.related_objects.all() from scratch which leads to appear unexpected objects (those having is_removed=True) in api response in an unpredictable order.

So in general I think just re-prefetching them would do the right job.

dr-ftvkun avatar Jun 03 '22 08:06 dr-ftvkun

Okay. I can't say that I know those bits of private implementation, but I'm okay with this.

Marking it as a priority, so I can verify to myself that the change does fix the behaviour as described above. Once that's confirmed I think we should be okay to merge this.

tomchristie avatar Jun 06 '22 12:06 tomchristie

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Aug 12 '22 07:08 stale[bot]

As this is buggy in current main/master branch, as explained by @dr-ftvkun above, I also think this should be merged.

fjsj avatar Aug 26 '22 12:08 fjsj

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Oct 29 '22 03:10 stale[bot]

Can we re-open it?

yuekui avatar Nov 23 '22 05:11 yuekui

@tomchristie could you please re-open it?

Hoping one day someone (mb me?) will have enough energy to push it to become a part of DRF or be rejected by a good reason (not just because it got stale).

dr-ftvkun avatar Nov 23 '22 05:11 dr-ftvkun

Hey good people, I'm a new maintainer here. you can ping me anytime for reviewing and insights for direction. if we are unsure about anything we then ping him for final call. I have already reviewed and merged some old pr. so in coming weeks this project will have more active maintainers available.

auvipy avatar Nov 23 '22 06:11 auvipy

Hey good people, I'm a new maintainer here. you can ping me anytime for reviewing and insights for direction. if we are unsure about anything we then ping him for final call. I have already reviewed and merged some old pr. so in coming weeks this project will have more active maintainers available.

Hey @auvipy! Great news!

I think this PR at least needs tests for the cases i provided above.

But still, could you also look at it to check the general idea?

dr-ftvkun avatar Nov 23 '22 06:11 dr-ftvkun

I will review this thoroughly

auvipy avatar Nov 23 '22 12:11 auvipy

Hey good people, I'm a new maintainer here. you can ping me anytime for reviewing and insights for direction. if we are unsure about anything we then ping him for final call. I have already reviewed and merged some old pr. so in coming weeks this project will have more active maintainers available.

Hey @auvipy! Great news!

I think this PR at least needs tests for the cases i provided above.

But still, could you also look at it to check the general idea?

Thanks @dr-ftvkun , I'll add tests for that.

yuekui avatar Nov 24 '22 00:11 yuekui

Hi @auvipy please let me know if there's any improvement we could do for this PR.

yuekui avatar Dec 02 '22 22:12 yuekui

we need to verify the usage of django internals here. so need little bit more time then expected. please allow us some time to get back to you for this.

auvipy avatar Dec 05 '22 06:12 auvipy

we got a regression report, also a possible fix, can you check? https://github.com/encode/django-rest-framework/pull/9314

auvipy avatar Mar 20 '24 11:03 auvipy

we got a regression report, also a possible fix, can you check? https://github.com/encode/django-rest-framework/pull/9314

Yeah that should fix the case that if only get_object() was defined, it looks good to me.

yuekui avatar Mar 20 '24 15:03 yuekui