2017-04-17 1 views
3

Ich verwende Django 1.8.wie die Ausgabe von Count() in Django auf FloatField in Django 1.8

Ich habe zwei Modelle: -

class Query(models.Model): 
    user = models.ForeignKey(settings.AUTH_USER_MODEL) 
    title = models.TextField() 
    details = models.TextField() 
    pub_date = models.DateTimeField('date published') 
    post_score=models.FloatField(default=0.0) 
    .... 

class Tags(models.Model): 
    """docstring for Tags""" 
    tagname=models.TextField() 
grouppostlist=models.ManyToManyField(Query,through='GroupPostsTag',through_fields=('tag','query')) 

# and another model(it stores tags for a query) 

class GroupPostsTag(models.Model): 
    query=models.ForeignKey('Query') 
    tag=models.models.ForeignKey('Tags') 

Jetzt möchte ich Anfragen sortieren, basierend auf der Summe aus „Anzahl von Tags“ und Abfrage „post_score“. Ich suche etwas wie folgt aus: -

tagged_user_posts = Query.objects.filter(Q(tags__id__in=tags_list)).annotate(num_tags=Cast(Count('tags'),models.FloatField())).annotate(post_scores=F('num_tags')+F('post_score')).order_by('-post_scores') 

Cast in django 1.10 vorgesehen ist. Also welche Alternative kann ich verwenden?

+0

Es ist Open Source. Sie können einfach die [Quelle der 'Cast' Klasse] (https://docs.djangoproject.com/en/1.10/_modules/django/db/models/functions/base/#Cast) kopieren und in einer Datei speichern dein Projekt. – xyres

+0

Ich versuchte das, aber es gab mir einen Fehler: 'TypeError: as_sql() hat ein unerwartetes Schlüsselwortargument 'db_type'' – badiya

+0

Ich habe den Quellcode ein wenig geändert und fügte es in einer Antwort hinzu. Ich hoffe, das hilft. – xyres

Antwort

3

Wie ich in meinem Kommentar gesagt habe, können Sie einfach den Quellcode von Cast Klasse kopieren und speichern Sie es in Ihren Projekten und verwenden Sie es.

Es stellte sich heraus, es war nicht so einfach wie das. Sie müssen auch die Cast.as_sqlas it is in v1.10 ändern. Und, keine Notwendigkeit, einen super Anruf zu zu machen.

Kopieren Sie einfach den folgenden Code und speichern Sie ihn in Ihrem Projekt. Ich habe es getestet und es funktioniert.

+0

Ja, gute Arbeit. Einfach runterzählen, ohne zu kommentieren warum. Sie können zumindest angeben, was diese Antwort fehlt, damit ich versuchen kann, sie zu verbessern. – xyres

1

Wie Sie in Frage für Django 1.10 erwähnt haben, können Sie die integrierte Cast-Funktion verwenden. Für ältere Versionen können Sie Func() expression verwenden

from django.db.models import Count, Func, F, ExpressionWrapper, FloatField 
tagged_user_posts = Query.objects.filter(Q(tags__id__in=tags_list)). 
    annotate(num_tags=Func(Count('tags'), 
          template='%(function)s(%(expressions)s AS %(type)s)', 
          function='Cast', 
          type='float') 
    ). 
    annotate(post_scores=ExpressionWrapper(F('num_tags')+F('post_score'), output_field=FloatField())). 
    order_by('-post_scores') 
+0

es zeigte einen Fehler 'FieldError: Ausdruck enthält gemischte Typen. Sie müssen output_field' setzen – badiya

+0

Die Zusammenfassung der F-Objekte mit ExpressionWrapper sollte dieses Problem beheben. Probieren Sie es jetzt. –

Verwandte Themen