Ich habe Knoten- und Benutzermodelle, die beide zu einer Organisation gehören. Ich möchte sicherstellen, dass ein Benutzer immer nur Knoteninstanzen sieht, die zu seiner Organisation gehören.
Zu diesem Zweck möchte ich den Node Objects Manager mit einem überschreiben, der eine Abfrage_Satz von benutzerdefinierten gefilterten Ergebnissen zurückgibt.
Basierend auf https://docs.djangoproject.com/de/2.1/topics/db/managers/#modifying-a-manager-s-initial-queryset ist der relevante models.py- Code, den ich habe, unten:
class Organisation(models.Model):
users = models.ManyToManyField(User, related_name='organisation')
...
class UserNodeManager(models.Manager):
def get_queryset(self, request):
return super().get_queryset().filter(organisation=self.request.user.organisation.first())
class Node(models.Model):
organisation = models.ForeignKey(
Organisation, related_name='nodes', on_delete=models.CASCADE)
uuid = models.UUIDField(primary_key=True, verbose_name="UUID")
...
objects = UserNodeManager
views.py
class NodeListView(LoginRequiredMixin, generic.ListView):
model = Node
BEARBEITEN Ich kann einzelnen Ansichten ein benutzerdefiniertes Abfrageset hinzufügen. Dies funktioniert wie folgt:
views.py
class NodeListView(LoginRequiredMixin, generic.ListView):
model = Node
def get_queryset(self):
return Node.objects.filter(organisation__users__id=self.request.user.pk)
Meine Absicht ist es jedoch, DRY zu sein und eine 'master'-query_set-Methode an einem einzelnen Punkt zu überschreiben, damit jede Ansicht (z. B. Formular-Dropdown-Liste, API-Endpunkt) die vom Benutzer eingeschränkte Abfrage ohne zusätzlichen Code ausführt.
Ich verwende beispielsweise die allgemeinen Listenansichten von django und habe ein Formular zum Hinzufügen eines Scan-Objekts, bei dem ein Benutzer einen Knoten auswählen muss, zu dem der Scan gehört. Das Formular zeigt derzeit Knoten von anderen Organisationen an, was gegen die von mir benötigte Berechtigungslogik verstößt.
Leider scheint die überschriebene Node.objects-Eigenschaft keine Auswirkung zu haben und jeder Benutzer kann alle Knoten sehen. Verfolge ich den richtigen Ansatz?
Ich denke das Problem ist hier:
objects = UserNodeManager
Sie müssen die UserNodeManager
Instanz wie folgt initiieren :
objects = UserNodeManager()
Außerdem sollte beim Aufrufen der YourModel.objects.all()
Methode (die von der angezeigten Methode aufgerufen wird get_queryset
) ein Fehler ausgegeben werden , da sie beim Aufrufen der get_queryset()
Methode nicht übergeben wird request
. Ich denke, es wäre ein besserer Ansatz:
class UserNodeManager(models.Manager):
def all(self, request=None):
qs = super(UserNodeManager, self).all()
if request:
return qs.filter(...)
return qs
Oder Sie können eine neue Manager-Methode wie folgt erstellen (optional):
class UserNodeManager(models.Manager):
def user_specific_nodes(self, request):
return self.get_queryset().filter(...)
Aktualisieren Sie auch in der Ansicht:
class NodeListView(LoginRequiredMixin, generic.ListView):
model = Node
def get_queryset(self):
return Node.objects.all(self.request) # where you can obviously use filter(...) or Model.objects.user_specific_nodes(self.request)
aus Kommentaren
Die Sache ist, dass Sie request
mit filter()
oder bestehen müssen all()
. In generischen Ansichten gibt die get_queryset
Methode diese Informationen nicht an weiter all()
. Also musst du das so oder so passieren. Es gibt eine andere Möglichkeit, eine Middleware wie diese Django-Crequest zu verwenden . Sie können es so verwenden:
from crequest.middleware import CrequestMiddleware
class UserNodeManager(models.Manager):
def all(self):
qs = super(UserNodeManager, self).all()
request = CrequestMiddleware.get_request()
return qs.filter(...)
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen