2016-07-22 7 views
2

Gegeben, dass ich ein Django-Modell habe, das einen ForeignKey hat, der mit sich selbst verknüpft ist.Django-Benutzeranfragesatz mit Gruppennamen annotieren

class DjangoModel(): 

    [...] 

    successor = models.ForeignKey('self', null=True) 

konnte ich eine benutzerdefinierte django Datenbank Funktion wie folgt schreiben:

from django.db.models import BooleanField 
from django.db.models import Func 


class IsNull(Func): 
    """ 
    See docs: https://docs.djangoproject.com/en/1.8/ref/models/database-functions/ 
    """ 
    template = '%(expressions)s IS NULL' 

    def __init__(self, *args, **kwargs): 
     kwargs['output_field'] = BooleanField() 
     super(IsNull, self).__init__(*args, **kwargs) 

So kann ich dies tun:

queryset = DjangoModel.objects.all() 
queryset = queryset.annotate(**{'is_latest': IsNull('successor')}) 

und wenn die Verwendung queryset.values() .. ich

[{'pk': 1, is_latest': True}, {'pk': 2, 'is_latest': False}, ] 

wo e is_latest == True, wenn das Feld successor für ein Objekt NULL ist.

Jetzt möchte ich etwas ähnliches tun, aber habe keine Ahnung, wo ich anfangen soll!

Die gebündelte django.contrib.auth.models.User hat eine ManyToMany Beziehungen zu Modell

Für mein Projekt gibt es mehrere Benutzergruppentypen, zB Kunde/Marketing/Finanzen usw.

Was ich .. tun möchte, ist ein mit Anmerkungen versehen User queryset mit is_FOO Feld FOO ist ein Gruppenname. So zB is_customer oder is_marketing

wenn ich .values() auf einem queryset verwenden, sollte ich so etwas wie dieses:

[{'pk': 1, 'is_customer': True, 'is_marketing': False }, {'pk': 1, 'is_customer': True, 'is_marketing': True }] 

Der Gruppenname fest einprogrammiert werden könnte, zum Beispiel

queryset.annotate(**{'is_customer': IsGroupMember('customer')}) 

ich nur Hilfe benötigen mit der IsGroupMember Datenbankfunktion!

Ist das überhaupt möglich? Irgendwelche Tipps oder Tipps, um mich zu beginnen?

Jede Hilfe wird wirklich geschätzt. Vielen Dank

Antwort

1

Ich habe 2 Lösungen für das Problem :-)

Da ich die django Auth Benutzermodell bin mit

from django.contrib.auth.models import User 

und den Gruppennamen mich interessiert:

CUSTOMER_GROUP_NAME = 'customer' 

Lösung 1 - wie invon Todor Velichkov vorgeschlagenGoogle-Gruppe.

from django.db.models.expressions import RawSQL 


def is_group_member(group_name): 
    return RawSQL("""EXISTS(
     SELECT 1 FROM `auth_group` 
     WHERE `auth_group`.`name` = %s 
      AND `auth_group`.`id` IN (
       SELECT `auth_user_groups`.`group_id` 
       FROM `auth_user_groups` 
       WHERE `auth_user_groups`.`user_id` = `auth_user`.`id` 
      ) 
    )""", (group_name,), output_field=BooleanField()) 


qs1 = User.objects.all().annotate(is_customer=is_group_member(CUSTOMER_GROUP_NAME)) 

Link zur ursprünglichen Antwort:

Slightly Version seiner Antwort unter modifizierten https://groups.google.com/d/msg/django-users/BLCGZtUzEcY/w5w87frbBgAJ


ich etwas mehr Forschung getan und gelernt, über django bedingte Ausdrücke.

Docs: https://docs.djangoproject.com/en/1.9/ref/models/conditional-expressions/

Lösung 2 - django Ausdrücke :-)

from django.contrib.auth.models import User 
from django.db.models import BooleanField 
from django.db.models import When, Case, Value 

query = When(groups__name__in=[CUSTOMER_GROUP_NAME, ], then=Value(1)) 
qs2 = User.objects.annotate(
    is_customer=Case(query, default=Value(0), output_field=BooleanField())) 

Ich denke, mit "Lösung 2" ist sauberer und leichter zu lesen. Also werde ich das verwenden :-)

Verwandte Themen