2008-10-01 22 views
10

Je suis allé à toute la documentation, aussi je suis allé au canal IRC (BTW une grande communauté) et ils m'ont dit qu'il n'est pas possible de créer un modèle et limiter les choix dans un champ où l'utilisateur actuel est dans une ForeignKey. Je vais essayer d'expliquer cela par un exemple:Modèle limit_choices_to = {'user': user}

class Project(models.Model): 
    name = models.CharField(max_length=100) 
    employees = models.ManyToManyField(Profile, limit_choices_to={'active': '1'}) 

class TimeWorked(models.Model): 
    project = models.ForeignKey(Project, limit_choices_to={'user': user}) 
    hours = models.PositiveIntegerField() 

Bien sûr que le code ne fonctionne pas parce qu'il n'y a pas d'objet « utilisateur », mais c'était mon idée et je tentais d'envoyer l'objet de l'utilisateur 'au modèle pour limiter les choix où l'utilisateur actuel a des projets, je ne veux pas voir les projets où je ne suis pas.

Merci beaucoup si vous pouvez m'aider ou me donner des conseils, Je ne veux pas vous écrire toute l'application, juste une astuce comment faire face à cela. J'ai 2 jours dans ma tête et je ne peux pas sortir :(

MISE À JOUR: La solution est ici. http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/ envoyer request.user à un modèle

Répondre

1

Utilisez threadlocals si vous voulez obtenir utilisateur actuel qui édite ce modèle. Threadlocals middleware met l'utilisateur actuel dans une variable à l'échelle du processus. Prenez ce middleware

from threading import local 

_thread_locals = local() 
def get_current_user(): 
    return getattr(getattr(_thread_locals, 'user', None),'id',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) 

Consultez la documentation sur l'utilisation des classes de middleware. Alors ne importe où dans le code que vous pouvez appeler

user = threadlocals.get_current_user 
+0

Je vais essayer ça. – AbeEstrada

+5

c'est une mauvaise idée ... la raison pour laquelle vous devez faire un hack avec threadlocals est parce que cette validation * ne devrait pas être dans le modèle * – Anentropic

+1

D'accord. Il y a deux ans, cela semblait être une bonne idée –

-1

Hmmm, je ne pas pleinement Si vous ne pouvez pas le faire lorsque vous déclarez le modèle, vous pouvez peut-être obtenir la même chose avec les méthodes de la classe d'objets où vous "envoyez" l'objet utilisateur, peut-être commencer par le constructeur

+0

Par exemple, j'ai 10 projets, mais je suis juste à 3. Je veux obtenir un menu déroulant boîte avec seulement les 3 projets que je suis, je ne veux pas montrer tous les 10 projets. – AbeEstrada

4

Le modèle lui-même ne sait rien sur l'utilisateur actuel, mais vous pouvez donner à cet utilisateur dans une vue à la forme qui fonctionne modèles objets (et dans la forme réinitialiser choices pour le champ nécessaire).

Si vous avez besoin de ce sur le site admin - vous pouvez essayer raw_id_admin avec django-granular-permissions (http://code.google.com/p/django-granular-permissions/ mais je ne pouvais pas obtenir rapidement fonctionner sur mon django, mais il semble être assez frais pour 1.0 si ...). Enfin, si vous avez vraiment besoin d'une selectbox dans admin, vous aurez besoin de pirater django.contrib.admin lui-même.

0

Je ne suis pas sûr de comprendre exactement ce que vous voulez faire, mais je pense qu'il y a de bonnes chances que vous obteniez au moins une partie de la façon dont vous utilisez un custom Manager. En particulier, n'essayez pas de définir vos modèles avec des restrictions à l'utilisateur actuel, mais créez un gestionnaire qui renvoie uniquement les objets qui correspondent à l'utilisateur actuel.

1

Cette limitation de choix à l'utilisateur en cours est une sorte de validation qui doit se produire de façon dynamique dans le cycle de la demande, et non pas dans la définition du modèle statique . En d'autres termes: au moment où vous créez une instance de ce modèle, vous serez dans une vue et à ce stade, vous aurez accès à l'utilisateur actuel et pouvez limiter les choix.

Ensuite, vous avez juste besoin d'un ModelForm personnalisé pour transmettre la requête.utilisateur, voir l'exemple ici: http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/

from datetime import datetime, timedelta 
from django import forms 
from mysite.models import Project, TimeWorked 

class TimeWorkedForm(forms.ModelForm): 
    def __init__(self, user, *args, **kwargs): 
     super(ProjectForm, self).__init__(*args, **kwargs) 
     self.fields['project'].queryset = Project.objects.filter(user=user) 

    class Meta: 
     model = TimeWorked 

alors à votre avis:

def time_worked(request): 
    form = TimeWorkedForm(request.user, request.POST or None) 
    if form.is_valid(): 
     obj = form.save() 
     # redirect somewhere 
    return render_to_response('time_worked.html', {'form': form})