Модель limit_choices_to = {'user': user}

python django model

10185 просмотра

7 ответа

952 Репутация автора

Я пошел на всю документацию, также я пошел на канал IRC (Кстати, большое сообщество), и они сказали мне, что невозможно создать модель и ограничить выбор в поле, где «текущий пользователь» находится в ForeignKey. Я попытаюсь объяснить это на примере:

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

Конечно, этот код не работает, потому что нет объекта «пользователь», но это была моя идея, и я пытался отправить объект «пользователь» в модель, чтобы просто ограничить выбор, где текущий пользователь имеет проекты, я не не хочу видеть проекты, в которых я не нахожусь.

Большое спасибо, если вы можете мне помочь или дать какой-нибудь совет, я не хочу, чтобы вы написали все приложение, просто совет, как с этим справиться. У меня есть 2 дня с этим в моей голове, и я не могу понять это :(

ОБНОВЛЕНИЕ : решение здесь: http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/ отправка request.userмодели.

Автор: AbeEstrada Источник Размещён: 01.10.2008 10:14

Ответы (7)


-1 плюса

16872 Репутация автора

Хммм, я не до конца понимаю ваш вопрос. Но если вы не можете сделать это при объявлении модели, возможно, вы можете достичь того же с помощью переопределения методов класса объектов, куда вы «отправляете» пользовательский объект, возможно, начните с конструктора.

Автор: Vasil Размещён: 01.10.2008 10:24

4 плюса

4252 Репутация автора

Сама модель ничего не знает о текущем пользователе, но вы можете дать этому пользователю представление в форме, которая управляет объектами модели (и в сбросе формы choicesдля необходимого поля).

Если вам нужно это на сайте администратора - вы можете попробовать raw_id_adminвместе с django-granular-permissions( http://code.google.com/p/django-granular-permissions/, но я не смог быстро заставить его работать на моем django, но это, кажется, свежо достаточно для 1.0, так что ...).

В конце концов, если вам сильно нужен selectbox в админке - тогда вам нужно взломать django.contrib.adminсебя.

Автор: ilvar Размещён: 02.10.2008 12:47

0 плюса

4886 Репутация автора

Я не уверен, что полностью понимаю, что именно вы хотите сделать, но я думаю, что есть хороший шанс, что вы хотя бы частично добьетесь успеха, используя собственный менеджер . В частности, не пытайтесь определить ваши модели с ограничениями для текущего пользователя, но создайте менеджер, который возвращает только объекты, которые соответствуют текущему пользователю.

Автор: TimB Размещён: 02.10.2008 12:58

-1 плюса

24359 Репутация автора

Решение

Используйте threadlocals, если вы хотите получить текущего пользователя, который редактирует эту модель. Промежуточное ПО Threadlocals помещает текущего пользователя в переменную всего процесса. Возьми это промежуточное ПО

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)

Ознакомьтесь с документацией по использованию классов промежуточного программного обеспечения. Тогда в любом месте кода вы можете позвонить

user = threadlocals.get_current_user
Автор: Dmitry Shevchenko Размещён: 02.10.2008 10:09

1 плюс

952 Репутация автора

3 плюса

21128 Репутация автора

Это ограничение выбора для текущего пользователя является своего рода проверкой, которая должна происходить динамически в цикле запросов, а не в определении статической модели.

Другими словами: в момент создания экземпляра этой модели вы будете в представлении, и в этот момент у вас будет доступ к текущему пользователю и вы сможете ограничить выбор.

Тогда вам просто нужна пользовательская ModelForm для передачи в request.user, см. Пример здесь: 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

тогда по вашему мнению:

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})
Автор: Anentropic Размещён: 11.01.2011 09:52

0 плюса

320 Репутация автора

Используя основанные на классах общие представления в Django 1.8.x / Python 2.7.x, вот что я и мои коллеги придумали:

В models.py:

# ...

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

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

    # ...

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

# ...

В 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

В шаблонах / предложениях / 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 %}
Автор: Stephen G Tuggy Размещён: 28.03.2019 01:50
32x32