39 Stimmen

Django benutzerdefinierte Manager - wie kann ich nur Objekte zurückgeben, die vom angemeldeten Benutzer erstellt wurden?

Ich möchte den Modellmanager für benutzerdefinierte Objekte so überschreiben, dass nur Objekte zurückgegeben werden, die ein bestimmter Benutzer erstellt hat. Admin-Benutzer sollten weiterhin alle Objekte über den Objektmodellmanager zurückgeben.

Jetzt habe ich gefunden ein Ansatz die funktionieren könnten. Sie schlagen vor, Ihre eigene Middleware zu erstellen, die wie folgt aussieht:

#### myproject/middleware/threadlocals.py

try:
    from threading import local
except ImportError:
    # Python 2.3 compatibility
    from django.utils._threading_local import local

_thread_locals = local()

def get_current_user():
    return getattr(_thread_locals, 'user', None)

class ThreadLocals(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""
    def process_request(self, request):
        _thread_locals.user = getattr(request, 'user', None)

#### end

Und im Benutzerdefinierten Manager können Sie die get_current_user() Methode, um nur Objekte zurückzugeben, die ein bestimmter Benutzer erstellt hat.

class UserContactManager(models.Manager):
    def get_query_set(self):
        return super(UserContactManager, self).get_query_set().filter(creator=get_current_user())

Ist dies ein guter Ansatz für diesen Anwendungsfall? Wird das funktionieren? Oder ist das wie "mit dem Vorschlaghammer eine Nuss zu knacken" ;-)

Einfach benutzen:

Contact.objects.filter(created_by= user)

in jeder Ansicht sieht für mich nicht sehr ordentlich aus.

EDIT Verwenden Sie diesen Middleware-Ansatz nicht!!!

den von Jack M. unten beschriebenen Ansatz anwenden

Nach einer Weile des Testens verhielt sich dieser Ansatz ziemlich seltsam und mit diesem Ansatz verwechseln Sie einen globalen Zustand mit einer aktuellen Anfrage.

Verwenden Sie den unten dargestellten Ansatz. Es ist wirklich einfach und Sie müssen nicht mit der Middleware herumhacken.

Erstellen Sie in Ihrem Modell einen benutzerdefinierten Manager mit einer Funktion, die den aktuellen Benutzer oder einen beliebigen anderen Benutzer als Eingabe erwartet.

#in your models.py
class HourRecordManager(models.Manager):
    def for_user(self, user):
        return self.get_query_set().filter(created_by=user)

class HourRecord(models.Model):
    #Managers
    objects = HourRecordManager()

#in vour view you can call the manager like this and get returned only the objects from the currently logged-in user.

hr_set = HourRecord.objects.for_user(request.user)

Siehe auch dies Diskussion über den Middelware-Ansatz.

60voto

Jack M. Punkte 27217

Eine Möglichkeit, damit umzugehen, wäre, eine neue Methode zu erstellen, anstatt die get_query_set . Etwas in der Art von:

class UserContactManager(models.Manager):
    def for_user(self, user):
        return super(UserContactManager, self).get_query_set().filter(creator=user)

class UserContact(models.Model):
    [...]
    objects = UserContactManager()

So kann Ihre Ansicht wie folgt aussehen:

contacts = Contact.objects.for_user(request.user)

Dies sollte helfen, Ihre Ansicht einfach zu halten, und da Sie Djangos eingebaute Funktionen verwenden würden, ist es unwahrscheinlich, dass sie in Zukunft kaputt geht.

6voto

lprsd Punkte 80189

Es scheint notwendig zu sein, die Middleware zu verwenden, um die Benutzerinformationen zu speichern.

Ich möchte jedoch nicht, dass die Standard ModelManager objects , aber verbinden Sie es mit einem anderen Manager, den ich im Code verwenden werde, z. B. in Ihrem Fall user_objects anstelle von Objekten.

Da Sie dies nur innerhalb von Ansichten verwenden werden, die @login_required Sie brauchen nicht die ganze komplexe Fehlerbehandlung in der Middleware.

Nur meine 2 Cent.

-1voto

Dominik Szmaj Punkte 11

Oder noch einfacher: Verwenden Sie einen Fremdschlüssel, um den Abfragesatz abzurufen.

Wenn Sie ein solches Modell haben

class HourRecord(models.Model):
    created_by = ForeignKey(get_user_model(), related_name='hour_records')

Sie können abfragen HourRecords in einer Ansicht von Benutzer mit einfach:

request.user.hour_records.all()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X