提问人:AbeEstrada 提问时间:10/2/2008 最后编辑:juliomalegriaAbeEstrada 更新时间:3/28/2019 访问量:13473
模型 limit_choices_to={'user': user}
Model limit_choices_to={'user': user}
问:
我去了所有的文档,也去了 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
答:
嗯,我不完全理解你的问题。但是,如果你在声明模型时做不到,也许你可以用重写你“发送”用户对象的对象类的方法来实现同样的事情,也许从构造函数开始。
评论
模型本身对当前用户一无所知,但您可以在视图中为该用户提供操作模型对象的表单(并在表单中重置必要的字段)。choices
如果您在管理站点上需要它 - 您可以尝试(http://code.google.com/p/django-granular-permissions/ 但我无法快速让它在我的 django 上运行,但它似乎对 1.0 来说足够新鲜,所以......raw_id_admin
django-granular-permissions
最后,如果你在管理中非常需要一个选择框 - 那么你需要自己破解。django.contrib.admin
我不确定我是否完全理解您想要做什么,但我认为您很有可能至少会使用自定义管理器实现其中的一部分。特别是,不要尝试定义对当前用户有限制的模型,而是创建一个仅返回与当前用户匹配的对象的管理器。
如果要获取编辑此模型的当前用户,请使用 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
评论
这种对当前用户选择的限制是一种验证,需要在请求周期中动态发生,而不是在静态模型定义中。
换言之:在创建此模型的实例时,您将处于视图中,此时您将有权访问当前用户并可以限制选择。
然后,您只需要一个自定义的 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})
在 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
在 templates/proposals/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 %}
评论