2012-07-17 27 views
6

Ben ara modelleri (anahtar kelime aracılığıyla) (https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships) BenDjango tastypie: orta modeli

kullanılarak ManyToMany ilişkileri ile Tastypie kullanmaya çalışıyorum kullanarak bir m2m ilişkilerin ekstra değerlerini alma bu modellerle çalışırken:

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')) 

birçok çoğa ilişki getirebildiğini oldum ama değil ekstra alanlar . İşte benim tastypie kod: Bu gibi benim PointResource yılında hidrat oda değişkene bir yöntem kullanmak çalışıyorum

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'] 

:

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 

Ama sorun yarattığı olmasıdır Puanlarımın olduğu kadar çok sorgu: Bu, +8000 Puanınız olduğunda gerçek bir performans katil.

Performans kazanmak için herhangi bir kullanışlı kaynak bulamadık. QuerySet için kullanılabilir .extra() yöntemini kullanarak özel bir sorgu yapmayı düşünüyordum, ancak JOIN anahtar sözcüğü kullanılamıyor (yama birkaç ay önce reddedildi). Ve emin değilim SELECT alt sorguları hile yapardı.

cevap

7

PointPosition kaynağını kullanmak için sorgulamamızı değiştirmeyi düşündünüz mü? At

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

: "Nokta" veritabanınızda ne anlama geldiğini o sesler itibaren aslında iç ayrıntılarını gizlemek için bazı çeviri olması gerekir böylece "Nokta" API'nızdan ne anlama aynı değildir filtreleme parametrelerinizi ayarlamanız gerekliliği, bu da birden fazla sorgulama ihtiyacını ortadan kaldıracaktır. dehydrate yönteminiz, verileri gerektiği gibi değiştirebilir. Ayrıca, gerekli alanları yalnızca tam nesneler yerine bir sözlük olarak çıkarmak için .values()'u kullanarak bazı ek yükleri kaydedebilirsiniz.

+0

Cevabınız için çok teşekkürler. Bu aslında yaptığım şeydi, ancak diksiyonumu yeniden düzenlemek için öğeleri değiştirmek için "dehidrate" kullanmayı düşünmedim. Cool tip :) – Solvik

+1

Kendimi sadece basit bir veri yapısı oluşturduğunu ve bir sözlük oluşturmanın tek bir doğru yolu olmadığını hatırlatan önce tastipiyle dövüşmek için çok fazla zaman harcadım. Gnarly overridden ModelResource'ın karmaşık bir veri yapısını verimli bir şekilde oluşturmak için doğrudan ORM'yi doğrudan arayan basit bir Kaynak haline geldiği en az bir kaynağım var. –