2015-05-04 22 views
9

Oy verdiğim bir SerializerMethodField, örneğin, vote_count gibi sipariş vermek istediğim bir Forum Konu modelim var.Django Rest Framework Bir SerializerMethodField Üzerine Sipariş Verme

  1. OrderingFilter varsayılan olarak açıktır ve başarıyla /topics?ordering=title
  2. vote_count işlevi sipariş edebilirsiniz:

    İşte
    # models.py 
    class Topic(models.Model): 
        """ 
        An individual discussion post in the forum 
        """ 
        title = models.CharField(max_length=60) 
    
        def vote_count(self): 
         """ 
         count the votes for the object 
         """ 
         return TopicVote.objects.filter(topic=self).count() 
    
    
    # serializers.py 
    class TopicSerializer(serializers.ModelSerializer): 
        vote_count = serializers.SerializerMethodField() 
    
        def get_vote_count(self, obj): 
         return obj.vote_count() 
    
        class Meta: 
         model = Topic 
    
    
    # views.py 
    class TopicViewSet(TopicMixin, viewsets.ModelViewSet): 
        queryset = Topic.objects.all() 
        serializer_class = TopicSerializer 
    

    olanı ise: Burada çok basitleştirilmiş Modeli, seri hale ve ViewSet sorunu göstermek için vardır mükemmel çalışır

TopicSerializer'da MethodField tarafından sipariş vermek istiyorum, 0_gibi desteklenmiyor gibi görünüyor. Bu alandan sipariş verebilmemin bir yolu var mı?

Benim basitleştirilmiş JSON yanıtı şöyle görünür: Ben API tüketmek için Ember kullanıyorum ve ayrıştırıcı CamelCase bunu çeviriyor

{ 
    "id": 1, 
    "title": "first post", 
    "voteCount": 1 
}, 
{ 
    "id": 2, 
    "title": "second post", 
    "voteCount": 8 
}, 
{ 
    "id": 3, 
    "title": "third post", 
    "voteCount": 4 
} 

. Ben de sipariş = voteCount denedim ama bu işe yaramazsa (ve olmamalıdır)

cevap

18

sipariş veritabanı tarafında üzerinde uygulanır, çünkü bu, the default OrderingFilter kullanılarak mümkün değildir. Bu verimlilik nedenleriyle, manuel olarak sonuçları inanılmaz bir şekilde QuerySet standart bir kopmadan ve yavaşça kırmak anlamına gelebilir. Her şeyi QuerySet olarak tutarak, Django REST çerçevesi tarafından sağlanan (genellikle QuerySet) ve yerleşik sayfalama (bir tanesi olmadan yavaş olabilir) tarafından sağlanan yerleşik filtrelemeden yararlanabilirsiniz.

Şimdi, bu durumlarda iki seçeneğiniz var: veri tabanındaki değerinizi nasıl alacağınızı öğrenin ya da almanız gereken performans düşüşünü en aza indirmeye çalışın. İkinci seçenek çok uygulamaya özel olduğundan, şimdilik şimdilik atlayacağım.

Bu durumda, veritabanı tarafında sayım yapmak için Django tarafından sağlanan the Count function kullanabilirsiniz. Bu, the aggregation API'un bir parçası olarak sağlanır ve the SQL COUNT function gibi çalışır. Sen your related_name for the field (Eğer doğru bir set var?) Ile topicvote_set değiştirilmesi

queryset = Topic.objects.annotate(vote_count=Count('topicvote_set')) 

olmak görünümde senin queryset değiştirerek eşdeğer Count çağrıyı yapabilirsiniz. Bu, sonuçları oy sayısına dayalı olarak sipariş vermenize ve hatta sorgulamanın kendisinde mevcut olduğundan filtrelemeyi (isterseniz) yapmanızı sağlayacaktır.

Bu, seri hale getiricinizde küçük bir değişiklik yapılmasını gerektirir, bu nedenle nesneler üzerinde bulunan yeni vote_count özelliğinden yararlanır. Eğer açıklarken (eski yöntem yerini alamaz ise) kullanılan değişken adlandırmak isteyebilirsiniz

class TopicSerializer(serializers.ModelSerializer): 
    vote_count = serializers.IntegerField(read_only=True) 

    class Meta: 
     model = Topic 

Bu, mevcut vote_count yöntemini geçersiz kılar.


Ayrıca, bir Django DİNLENME çerçeve alanının source gibi bir yöntem adı geçebilir ve onu otomatik olarak arayacak.Yani teknik Mevcut serileştirici sadece

class TopicSerializer(serializers.ModelSerializer): 
    vote_count = serializers.IntegerField(read_only=True) 

    class Meta: 
     model = Topic 

olabilir Ve şu anda yaptığı gibi o tam çalışacak. Bu durumda read_only'un gerekli olduğunu unutmayın, çünkü bir yöntem bir özellik ile aynı değildir, bu nedenle değer ayarlanamaz.

+0

Harika bir cevap, 2 oy verseydim verebilirdim! Mükemmel bir şekilde çalışıyor ve MethodField'tan kurtulmanın son ipucu için teşekkürler. – awwester

İlgili konular