2017-07-26 2 views
0

Comment puis-je commander un Django QuerySet à partir d'un champ de sérialiseur? Puisque le champ est trop compliqué, je ne pouvais pas commander le QuerySet en utilisant annotate et je ne peux pas stocker la valeur dans le modèle aussi.Comment commander un queryset de cadre de repos django à partir du champ sérialiseur?

Edit:

sérialiseur

class DrinkListModelSerializer(serializers.ModelSerializer): 
    count_need = serializers.SerializerMethodField() 
    url = drink_detail_url 

    class Meta: 
     model = Drink 
     fields = [ 
      'name', 
      'count_need', 
      'thumbnail', 
      'url' 
     ] 

    def get_count_need(self, obj): 
     drink_ingredient_qs = obj.ingredients.all() 
     user = self.context['request'].user 
     user_qs = User.objects.filter(username=user.username) 
     if user_qs.exists() and user_qs.count() == 1: 
      user_obj = user_qs.first() 
      user_ingredient_qs = user_obj.ingredient_set.all() 
      return (user_ingredient_qs & drink_ingredient_qs).count() 
     return 0 

Modèles:

class Drink(models.Model): 
    name    = models.CharField(max_length = 1000, null=True, blank=True) 
    ingredients   = models.ManyToManyField(Ingredient, blank=True) 
    user    = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True) 

class Ingredient(models.Model): 
    name    = models.CharField(max_length = 1000) 
    ingredient_category = models.ForeignKey(Category, null=True, blank=True) 
    slug    = models.SlugField(max_length=255, unique=True) 
    user    = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True) 

Voir

class DrinkListAPIView(ListAPIView): 
serializer_class = DrinkListModelSerializer 
pagination_class = LargeResultsSetPagination 
permission_classes = [AllowAny] 

def get_queryset(self, *args, **kwargs): 
    user = self.request.user 
    qs = Drink.objects.all() 
    userQuery = self.request.GET.get('user') 
    query = self.request.GET.get("q") 
    filters = self.request.GET.getlist('filter') 
    if query: 
     qs = qs.filter(name__icontains=query) 
    elif filters: 
     qs = qs.filter(playlist__name__iexact=filters[0]) 
     for filter in filters[1:]: 
      qs = qs | Drink.objects.filter(playlist__name__iexact=filter) 
    elif userQuery and user.is_authenticated(): 
     qs = qs.filter(user=user) 
    return qs.order_by('-timestamp') 

Actuellement, je commande la queryset par horodatage, car il est dans le modélisez-le, mais J'ai besoin de le commander par 'count_need' qui fait partie du sérialiseur. J'ai essayé de faire quelque chose comme qs = qs.annotate(count_need=Count('ingredients' & user_ingredient_qs)).order_by(count_need) mais cela ne marche pas clairement puisque les «ingrédients» sont juste une chaîne ici et pas le queryset d'ingrédient de la boisson.

+1

Pouvez-vous fournir vos modèles, sérialiseur, et voir s'il vous plaît. – mattjegan

+0

Je viens d'éditer le message original –

Répondre

0

Une façon qui pourrait bien fonctionner est de mettre en œuvre et personnaliser to_representation sur la liste sérialiseur:

def to_representation(self, data): 
    iterable = data.all() if isinstance(data, models.Manager) else data 

    iterable = sorted(iterable, key=lambda x: x.count_need) 

    return [ 
     self.child.to_representation(item) for item in iterable 
    ] 
+0

Hmm je viens de l'essayer et je reçois "Typeerror: Buvez objet n'est pas itérable" sur la ligne triée, des suggestions? –

+0

Il semble que vous ne passez qu'une seule instance dans le sérialiseur, essayez d'ajouter 'many = True' lors de l'initialisation du sérialiseur. – mattjegan