Domanda

Sono andato a tutta la documentazione, inoltre sono andato al canale IRC (a proposito di una grande comunità) e mi hanno detto che non è possibile creare un modello e limitare le scelte in un campo in cui "l'utente corrente" si trova in un ForeignKey. Proverò a spiegarlo con un esempio:

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()

Ovviamente quel codice non funziona perché non esiste un oggetto "utente", ma questa era la mia idea e stavo cercando di inviare l'oggetto "utente" al modello per limitare le scelte in cui l'utente corrente ha progetti , Non voglio vedere progetti in cui non mi trovo.

Grazie mille se mi puoi aiutare o darmi qualche consiglio, non voglio che tu scriva tutta l'app, solo un consiglio su come gestirlo. Ho 2 giorni con questo in testa e non riesco a capirlo :(

AGGIORNAMENTO : la soluzione è qui: http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/ inviando request.user a un modello .

È stato utile?

Soluzione

Usa threadlocals se vuoi ottenere utente corrente che modifica questo modello. Il middleware Threadlocals mette l'utente corrente in una variabile a livello di processo. Prendi questo 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)

Controlla la documentazione su come utilizzare le classi del middleware. Quindi ovunque nel codice puoi chiamare

user = threadlocals.get_current_user

Altri suggerimenti

Il modello stesso non sa nulla sull'utente corrente, ma è possibile fornire all'utente in una vista il modulo che gestisce gli oggetti del modello (e nel modulo ripristinare scelte per il campo necessario).

Se ne hai bisogno sul sito di amministrazione, puoi provare raw_id_admin insieme a django-granular-Permissions ( http://code.google.com/p/django-granular-permissions/ ma non sono riuscito a farlo rapidamente funzionare il mio django ma sembra essere abbastanza fresco per 1.0 quindi ...).

Alla fine, se hai bisogno pesantemente di una casella di selezione in admin - allora dovrai hackerare django.contrib.admin stesso.

Questa limitazione delle scelte all'utente corrente è un tipo di convalida che deve avvenire in modo dinamico nel ciclo di richiesta, non nella definizione statica del modello.

In altre parole: nel punto in cui si sta creando una istanza di questo modello, ci si troverà in una vista e a quel punto si avrà accesso all'utente corrente e si potranno limitare le scelte.

Quindi hai solo bisogno di un ModelForm personalizzato per passare il request.user a, vedi l'esempio qui: http://collingrady.wordpress.com/2008/ 07/24 / utili-form-trucchi-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

quindi a tuo avviso:

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})

Usando le viste generiche basate sulla classe in Django 1.8.x / Python 2.7.x, ecco cosa sono venuti fuori con i miei colleghi:

In models.py:

# ...

class Proposal(models.Model):
    # ...

    # Soft foreign key reference to customer
    customer_id = models.PositiveIntegerField()

    # ...

In forms.py:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.forms import ModelForm, ChoiceField, Select
from django import forms
from django.forms.utils import ErrorList
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from .models import Proposal
from account.models import User
from customers.models import customer



def get_customers_by_user(curUser=None):
    customerSet = None

    # Users with userType '1' or '2' are superusers; they should be able to see
    # all the customers regardless. Users with userType '3' or '4' are limited
    # users; they should only be able to see the customers associated with them
    # in the customized user admin.
    # 
    # (I know, that's probably a terrible system, but it's one that I
    # inherited, and am keeping for now.)
    if curUser and (curUser.userType in ['1', '2']):
        customerSet = customer.objects.all().order_by('company_name')
    elif curUser:
        customerSet = curUser.customers.all().order_by('company_name')
    else:
        customerSet = customer.objects.all().order_by('company_name')

    return customerSet


def get_customer_choices(customerSet):
    retVal = []

    for customer in customerSet:
        retVal.append((customer.customer_number, '%d: %s' % (customer.customer_number, customer.company_name)))

    return tuple(retVal)


class CustomerFilterTestForm(ModelForm):

    class Meta:
        model = Proposal
        fields = ['customer_id']

    def __init__(self, user=None, *args, **kwargs):
        super(CustomerFilterTestForm, self).__init__(*args, **kwargs)
        self.fields['customer_id'].widget = Select(choices=get_customer_choices(get_customers_by_user(user)))

# ...

In views.py:

# ...

class CustomerFilterTestView(generic.UpdateView):
    model = Proposal
    form_class = CustomerFilterTestForm
    template_name = 'proposals/customer_filter_test.html'
    context_object_name = 'my_context'
    success_url = "/proposals/"

    def get_form_kwargs(self):
        kwargs = super(CustomerFilterTestView, self).get_form_kwargs()
        kwargs.update({
            'user': self.request.user,
        })
        return kwargs

In modelli / proposte / customer_filter_test.html:

{% extends "base/base.html" %}

{% block title_block %}
<title>Customer Filter Test</title>
{% endblock title_block %}

{% block header_add %}
<style>
    label {
        min-width: 300px;
    }
</style>
{% endblock header_add %}

{% block content_body %}
<form action="" method="POST">
    {% csrf_token %}
    <table>
        {{ form.as_table }}
    </table>
    <input type="submit" value="Save" class="btn btn-default" />
</form>
{% endblock content_body %}

Non sono sicuro di aver capito esattamente cosa vuoi fare, ma penso che ci siano buone probabilità che tu abbia almeno una parte del modo in cui usi un gestore personalizzato . In particolare, non provare a definire i tuoi modelli con restrizioni per l'utente corrente, ma crea un gestore che restituisca solo oggetti che corrispondono all'utente corrente.

Hmmm, non capisco perfettamente la tua domanda. Ma se non riesci a farlo quando dichiari il modello, forse puoi ottenere la stessa cosa con metodi prioritari della classe di oggetti in cui invii " l'oggetto utente, forse inizia con il costruttore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top