Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f0bda69

Browse files
committed
Updating docs to reflect the added ModelViewSet helper
1 parent f924ac8 commit f0bda69

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

‎docs/usage.md‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ REST_FRAMEWORK = {
2323
),
2424
'DEFAULT_RENDERER_CLASSES': (
2525
'rest_framework_json_api.renderers.JSONRenderer',
26-
'rest_framework.renderers.BrowsableAPIRenderer',
26+
# If you're performance testing, you will want to use the browseable API
27+
# without forms, as the forms can generate their own queries.
28+
# If performance testing, enable:
29+
# 'example.utils.BrowsableAPIRendererWithoutForms',
30+
# Otherwise, to play around with the browseable API, enable:
31+
'rest_framework.renderers.BrowsableAPIRenderer'
2732
),
2833
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
2934
}
@@ -36,6 +41,12 @@ retrieve the page can be customized by subclassing `PageNumberPagination` and
3641
overriding the `page_query_param`. Page size can be controlled per request via
3742
the `PAGINATE_BY_PARAM` query parameter (`page_size` by default).
3843

44+
#### Performance Testing
45+
46+
If you are trying to see if your viewsets are configured properly to optimize performance,
47+
it is preferable to use `example.utils.BrowsableAPIRendererWithoutForms` instead of the default `BrowsableAPIRenderer`
48+
to remove queries introduced by the forms themselves.
49+
3950
### Serializers
4051

4152
It is recommended to import the base serializer classes from this package
@@ -558,6 +569,39 @@ class QuestSerializer(serializers.ModelSerializer):
558569
`included_resources` informs DJA of **what** you would like to include.
559570
`included_serializers` tells DJA **how** you want to include it.
560571

572+
#### Performance improvements
573+
574+
Be aware that using included resources without any form of prefetching **WILL HURT PERFORMANCE** as it will introduce m*(n+1) queries.
575+
576+
A viewset helper was designed to allow for greater flexibility and it is automatically available when subclassing
577+
`views.ModelViewSet`
578+
```
579+
# When MyViewSet is called with ?include=author it will dynamically prefetch author and author.bio
580+
class MyViewSet(viewsets.ModelViewSet):
581+
queryset = Book.objects.all()
582+
prefetch_for_includes = {
583+
'__all__': [],
584+
'author': ['author', 'author__bio']
585+
'category.section': ['category']
586+
}
587+
```
588+
589+
The special keyword `__all__` can be used to specify a prefetch which should be done regardless of the include, similar to making the prefetch yourself on the QuerySet.
590+
591+
Using the helper instead of prefetching/selecting everything manually will prevent django from trying to load what could be a significant amount of data in memory for every single request.
592+
593+
> If you have a single model, e.g. Book, which has four relations e.g. Author, Publisher, CopyrightHolder, Category.
594+
>
595+
> To display 25 books in DRF without any includes, I would need a single query: SELECT * FROM book.
596+
>
597+
> To display 25 books DRF-JSONAPI without any includes, I would need either:
598+
> a) 1 query ala SELECT * FROM books LEFT JOIN author LEFT JOIN publisher LEFT JOIN CopyrightHolder LEFT JOIN Category
599+
> b) 4 queries with prefetches.
600+
>
601+
> Let's say I have 1M books, 50k authors, 10k categories, 10k copyrightholders. In the select_related scenario, you've just created a in-memory table with 1e18 rows ... do this a few times per second and you have melted your database. All to display 25 rows, with no included relationships. So select_related is only going to work if you have a small dataset or a small volume of traffic.
602+
>
603+
> -- <cite> Aidan Lister in issue [#337](https://github.com/django-json-api/django-rest-framework-json-api/issues/337#issuecomment-297335342)</cite>
604+
561605
<!--
562606
### Relationships
563607
### Errors

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /