mirror of
				https://github.com/HackSoftware/Django-Styleguide.git
				synced 2025-10-30 23:27:25 +03:00 
			
		
		
		
	Expand section for advanced serialization
This commit is contained in:
		
							parent
							
								
									f200a06334
								
							
						
					
					
						commit
						4a5a6e3604
					
				
							
								
								
									
										70
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								README.md
									
									
									
									
									
								
							|  | @ -864,7 +864,75 @@ The implementation of `inline_serializer` can be found [here](https://github.com | ||||||
| 
 | 
 | ||||||
| ### Advanced serialization | ### Advanced serialization | ||||||
| 
 | 
 | ||||||
| *Coming soon* | Sometimes, the end result of an API can be quite complex. Sometimes, we want to optimize the queries that we do and the optimization itself is quite complex. | ||||||
|  | 
 | ||||||
|  | Trying to stick with just an `OutputSerializer` in that case might limit our options. | ||||||
|  | 
 | ||||||
|  | In those cases, we can implement our output serialization as a function, and have the optimizations we need there. | ||||||
|  | 
 | ||||||
|  | Lets take this API as an example: | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | class SomeGenericFeedApi(BaseApi): | ||||||
|  |     def get(self, request): | ||||||
|  |         feed = some_feed_get( | ||||||
|  |             user=request.user, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         data = some_feed_serialize(feed) | ||||||
|  | 
 | ||||||
|  |         return Response(data) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | In this scenario, `some_feed_get` has the responsibility of returning a list of feed items (can be ORM objects, can be just IDs). | ||||||
|  | 
 | ||||||
|  | And we want to push the complexity of serializing this feed, in an optimal manner, to the serializer function - `some_feed_serialize`. | ||||||
|  | 
 | ||||||
|  | This means we don't have to do any unnecessary prefetches & optimizations in `some_feed_get`. | ||||||
|  | 
 | ||||||
|  | Here's an example of `some_feed_serialize`: | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | class FeedItemSerializer(serializers.Serializer): | ||||||
|  |     ... some fields here ... | ||||||
|  |     calculated_field = serializers.IntegerField(source="_calculated_field") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def some_feed_serialize(feed: List[FeedItem]): | ||||||
|  |     feed_ids = [feed_item.id for feed_item in feed] | ||||||
|  | 
 | ||||||
|  |     # Refetch items with more optimizations | ||||||
|  |     # Based on the relations that are going in | ||||||
|  |     objects = FeedItem.objects.select_related( | ||||||
|  |       ... as complex as you want ... | ||||||
|  |     ).prefetch_related( | ||||||
|  |       ... as complex as you want ... | ||||||
|  |     ).filter( | ||||||
|  |       id__in=feed_ids | ||||||
|  |     ).order_by( | ||||||
|  |       "-some_timestamp" | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     some_cache = get_some_cache(feed_ids) | ||||||
|  | 
 | ||||||
|  |     result = [] | ||||||
|  | 
 | ||||||
|  |     for feed_item in objects: | ||||||
|  |         # An example, adding additional fields for the serializer | ||||||
|  |         # That are based on values outside of our current object | ||||||
|  |         # This may be some optimization to save queries | ||||||
|  |         feed_item._calculated_field = some_cache.get(feed_item.id) | ||||||
|  | 
 | ||||||
|  |         result.append(FeedItemSerializer(feed_item).data) | ||||||
|  | 
 | ||||||
|  |     return result | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | As you can see, this is a pretty generic example, but the idea is simple: | ||||||
|  | 
 | ||||||
|  | 1. Refetch your data, with the needed joins & prefetches. | ||||||
|  | 1. Fetch or build in-memory caches, that will save you queries for specific computed values. | ||||||
|  | 1. Return a result, that's ready to be an API response. | ||||||
| 
 | 
 | ||||||
| ## Urls | ## Urls | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user