2009-10-22 4 views
1

Je n'ai besoin de montrer à un utilisateur que les objets qu'il possède. Comme je dois le faire sur plus de 80% de mes vues, le codage en dur tue le DRY. Plus encore, il est absolument impératif qu'un utilisateur ne voit jamais les enregistrements appartenant à d'autres. Et le faire à la main (dans toutes les vues) semble également sujet à erreur.DRY: affiche uniquement les enregistrements appartenant à l'utilisateur. Possible avec models.Manager?

J'ai regardé des décorateurs (comme login_required), mais cela semble au début du processus de gestion des demandes. Est-il possible d'obtenir la valeur request.user dans un gestionnaire écrit personnalisé et faire quelque chose comme ceci:

class CustomerManager(models.Manager): 
    def get_query_set(self): 
     return super(CustomerManager, self).get_query_set().filter(created_by=request.user) 

Ou est l'objet manager comme «no go! comme la définition du modèle en ce qui concerne les informations de demande?

Merci beaucoup.


Ceci est la partie d'enregistrement des objets, mais purement ici en tant qu'élaboration et pas une lecture nécessaire.

La partie de sauvegarde est relativement sécurisée. J'ai changé la fonction object.save() sur le modèle de sorte qu'il prend l'ID utilisateur en tant que parm.

def save(self, userid): 
    self.created_by = userid  
    super(Customer, self).save(userid) 

De l'avis:

if form.is_valid(): 
    customer = form.save(commit=False) 
    customer.save(request.user) 

De cette façon, je ne besoin d'avoir la ligne ci-dessous à mon avis avant customer.save...

customer.created_by = request.user 

Et ce qui rend moins sujette aux erreurs.

Répondre

0

Je pense que le meilleur endroit pour cela peut être dans votre point de vue - même si je peux me tromper. Ajout de self.created_by = userid dans la méthode save() ne fait rien pour protéger les gens de en affichant l'information. Juste de le sauver.

Si vous utilisez un gestionnaire personnalisé pour un ensemble de requêtes par défaut, les 20% de vos vues n'auront pas de chance.

Je pense que vous avez besoin d'une vue - pourquoi ne pas créer votre propre vue générique une fois et ensuite la réutiliser?

def object_detail_user_only(request. queryset, **kwargs): 
    queryset = queryset.filter(created_by=request.user) 

    return list_detail.object_detail(request,queryset,**kwargs) 

Quelque chose comme ça (non testé)?

+0

Je ne suis pas d'accord que les vues sont le meilleur endroit. S'il place toute l'autorisation dans les vues, alors il est décidé de changer la technologie du client, tout ce qui doit être réécrit. Je fais mon autorisation dans le modèle. –

+0

Merci pour l'avis thornomad. Donc ce que vous dites est avoir une méthode supplémentaire dans views.py qui est en quelque sorte entre mes vues et base de données. Ainsi, à partir d'une vue réelle, appelez toujours "object_detail_user_only" et faites toujours une requête prédéfinie? – GerardJP

+0

@Sailing Judo: Ce n'est pas tellement l'autorisation, je me repose entièrement sur Django auth pour cela.Que le problème soit traité ou non dans les vues est un bon point cependant .. D'où ma question models.manager :) – GerardJP

5

Pourquoi ne pas définir une méthode qui va chercher des documents pour l'utilisateur dans le CustomerManager:

class CustomerManager(models.Manager): 
    def get_user_records(self, user): 
     return self.filter(created_by=user) 

Je laisserais le get_query_set unoverridden que je vois aucun avantage pour l'emporter dans votre cas.

+0

@Shanyu: Ceci semble une mise en œuvre assez douce (juste essayé :). Serait-il facile d'obtenir un tri/filtrage supplémentaire? Quelque chose comme ".order_by ('company_name')"? – GerardJP

+0

@Shanyu: Je l'ai essayé .. cela fonctionne: list = Customer.objects.get_user_records (request.user) .order_by ('company_name'). Reverse() – GerardJP

+0

@GerardJP: Vous pouvez chaîner les méthodes comme vous le souhaitez: Foo.objects. filter (..). exclude (..). order_by (..) [x: y] – shanyu

Questions connexes