Django tastypie: getting additional m2m ratios using an intermediate model

I am trying to use Tastypie with ManyToMany relationships using intermediate models ( via ) ( https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships )

I work with these models:

class Point(models.Model): ... value = models.FloatField(_('Value'), null=True) rooms = models.ManyToManyField('rooms.Room', through='points.PointPosition') class Room(models.Model): title = models.CharField(max_length=64) class PointPosition(models.Model): point = models.ForeignKey('points.Point', verbose_name=_('Point')) room = models.ForeignKey('rooms.Room', verbose_name=_('Room')) x = models.IntegerField(_('Y')) y = models.IntegerField(_('X')) 

I managed to find many-to-many relationships, but not extra fields . Here is my tasting code:

 class PointResource(ModelResource): class Meta: queryset = Point.objects.select_related( depth=10 ).prefetch_related('rooms').all() resource_name = 'point' allowed_methods = ['get'] ... value = fields.FloatField() rooms = fields.ToManyField('rooms.api.RoomResource', 'rooms', full=True) class RoomResource(ModelResource): class Meta: queryset = Room.objects.all() resource_name = 'room' allowed_methods = ['get'] 

I am trying to use the method to hydrate a room variable in my PointResource as follows:

 def dehydrate_rooms(self, bundle): rooms = [] for room in bundle.obj.rooms.all(): position = PointPosition.objects.get( room_id = room.pk, point_id = bundle.obj.pk) rooms.append({'id': room.pk, 'title': room.title, 'x': position.x, 'y': position.y}) return rooms 

But the problem is that it creates as many queries as I have: it is a real productivity killer if you have +8000 points.

I could not find useful resources to improve performance. I was thinking of doing a custom query using the .extra () method available for QuerySet, but the JOIN keyword is not available (the patch was refused a couple of months ago). And I'm not sure if SELECT subqueries will do the trick.

+6
source share
1 answer

Have you considered changing your request for using the PointPosition resource? Of the sounds of this, that β€œdot” in your database is actually not the same as β€œdot” in your API, so there must be some translation to hide the internal details:

 class PointResource(ModelResource): class Meta: queryset = PointPosition.objects.select_related("point", "room") resource_name = 'point' allowed_methods = ('get', ) 

Due to the need to configure filtering options, this will avoid the need to make multiple queries. Your dehydrate method can swap data as needed. You can also save some overhead by using .values() to pull out the required fields as a dictionary, rather than complete objects.

+7
source

Source: https://habr.com/ru/post/920697/


All Articles