Модель limit_choices_to = {'user': user}
Я пошел ко всей документации, также я пошел на канал IRC (BTW большое сообщество), и они сказали мне, что невозможно создать модель и ограничить выбор в поле, где "текущий пользователь" находится в Внешний ключ.
Я попытаюсь объяснить это на примере:
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 дня с этим в голове, и я не могу понять: (
UPDATE. Решение находится здесь: http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/ отправка request.user
в модель.
Ответы
Ответ 1
Используйте 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
Ответ 2
Сама модель не знает ничего о текущем пользователе, но вы можете дать этому пользователю вид в форме, которая управляет объектами моделей (и в форме reset choices
для необходимого поля).
Если вам это нужно на сайте администратора - вы можете попробовать raw_id_admin
вместе с django-granular-permissions
(http://code.google.com/p/django-granular-permissions/, но я не мог" t быстро заставить его работать на моем джанго, но он кажется достаточно свежим для 1.0, поэтому...).
Наконец, если вам тяжело нужен selectbox в admin - тогда вам нужно взломать django.contrib.admin
.
Ответ 3
Это ограничение выбора для текущего пользователя - это вид проверки, который должен выполняться динамически в цикле запроса, а не в определении статической модели.
Другими словами: в момент, когда вы создаете экземпляр этой модели, вы будете в представлении и в этот момент у вас будет доступ к текущему пользователю и может ограничить выбор.
Тогда вам просто нужна специальная модель 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})
Ответ 4
Вот Cookbook Threadlocals and User
Ответ 5
Я не уверен, что полностью понимаю, что вы хотите сделать, но я думаю, что есть хороший шанс, что вы получите хотя бы часть пути, используя пользовательский менеджер. В частности, не пытайтесь определить свои модели с ограничениями для текущего пользователя, но создайте диспетчер, который возвращает только те объекты, которые соответствуют текущему пользователю.
Ответ 6
Используя основанные на классах общие представления в 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 probably a terrible system, but it 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 %}
Ответ 7
Хммм, я не совсем понимаю ваш вопрос. Но если вы не можете сделать это, когда объявляете модель, возможно, вы можете добиться того же самого с помощью переопределяющих методов класса объектов, где вы "отправляете" объект пользователя, возможно, начинайте с конструктора.