python 模型 limit_choices_to={'user': user}
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/160009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Model limit_choices_to={'user': user}
提问by AbeEstrada
I went to all the documentation, also I went to the IRC channel (BTW a great community) and they told me that is not possible to create a model and limit choices in a field where the 'current user' is in a ForeignKey. I will try to explain this with an example:
我查看了所有文档,还访问了 IRC 频道(顺便说一句,一个很棒的社区),他们告诉我,在“当前用户”位于外键中的字段中,不可能创建模型并限制选择。我将尝试用一个例子来解释这一点:
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()
Of course that code doesn't work because there is no 'user' object, but that was my idea and I was trying to send the object 'user' to the model to just limit the choices where the current user has projects, I don't want to see projects where I'm not in.
当然,该代码不起作用,因为没有“用户”对象,但这是我的想法,我试图将对象“用户”发送到模型以限制当前用户拥有项目的选择,我不不想看到我不在的项目。
Thank you very much if you can help me or give me any advice, I don't want to you write all the app, just a tip how to deal with that. I have 2 days with this in my head and I can't figure it out :(
非常感谢你,如果你能帮助我或给我任何建议,我不想你写所有的应用程序,只是一个如何处理的提示。我脑子里有 2 天的时间,但我无法弄清楚:(
UPDATE: The solution is here: http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/sending request.user
to a model.
更新:解决方案在这里:http: //collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/发送request.user
到模型。
采纳答案by Dmitry Shevchenko
Use threadlocals if you want to get currentuser that edits this model. Threadlocals middleware puts current user into process-wide variable. Take this middleware
如果您想获取编辑此模型的当前用户,请使用 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)
Check the documentation on how to use middleware classes. Then anywhere in code you can call
查看有关如何使用中间件类的文档。然后你可以在代码中的任何地方调用
user = threadlocals.get_current_user
回答by ilvar
Model itself doesn't know anything about current user but you can give this user in a view to the form which operates models objects (and in form reset choices
for necessary field).
模型本身对当前用户一无所知,但您可以在视图中为该用户提供操作模型对象的表单(并在choices
必要字段的表单重置中)。
If you need this on admin site - you can try raw_id_admin
along with django-granular-permissions
(http://code.google.com/p/django-granular-permissions/but I couldn't rapidly get it working on my django but it seems to be fresh enough for 1.0 so...).
如果您在管理站点上需要这个 - 您可以尝试raw_id_admin
使用django-granular-permissions
( http://code.google.com/p/django-granular-permissions/但我无法在我的 django 上快速让它工作,但它似乎是新鲜的足够 1.0 所以......)。
At last, if you heavily need a selectbox in admin - then you'll need to hack django.contrib.admin
itself.
最后,如果您非常需要管理员中的选择框 - 那么您将需要自己破解django.contrib.admin
。
回答by Anentropic
This limiting of choices to current user is a kind of validation that needs to happen dynamically in the request cycle, not in the static Model definition.
这种对当前用户的选择限制是一种需要在请求周期中动态发生的验证,而不是在静态模型定义中。
In other words: at the point where you are creating an instanceof this model you will be in a View and at that point you will have access to the current user and can limit the choices.
换句话说:在您创建此模型的实例时,您将处于视图中,此时您将可以访问当前用户并可以限制选择。
Then you just need a custom ModelForm to pass in the request.user to, see the example here: http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/
然后你只需要一个自定义的 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
then in your view:
那么在你看来:
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})
回答by Stephen G Tuggy
Using class-based generic Views in Django 1.8.x / Python 2.7.x, here is what my colleagues and I came up with:
在 Django 1.8.x / Python 2.7.x 中使用基于类的通用视图,这是我和我的同事想出的:
In models.py:
在models.py中:
# ...
class Proposal(models.Model):
# ...
# Soft foreign key reference to customer
customer_id = models.PositiveIntegerField()
# ...
In forms.py:
在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:
在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 templates/proposals/customer_filter_test.html:
在模板/提案/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 %}
回答by AbeEstrada
回答by TimB
I'm not sure that I fully understand exactly what you want to do, but I think that there's a good chance that you'll get at least part the way there using a custom Manager. In particular, don't try to define your models with restrictions to the current user, but create a manager that only returns objects that match the current user.
我不确定我是否完全理解您想要做什么,但我认为您很有可能使用自定义 Manager至少获得部分方法。特别是,不要尝试定义对当前用户有限制的模型,而是创建一个仅返回与当前用户匹配的对象的管理器。
回答by Vasil
Hmmm, I don't fully understand your question. But if you can't do it when you declare the model maybe you can achieve the same thing with overriding methods of the class of objects where you "send" the user object, maybe start with the constructor.
嗯,我不完全理解你的问题。但是,如果您在声明模型时无法做到这一点,也许您可以通过覆盖“发送”用户对象的对象类的方法来实现相同的目的,也许可以从构造函数开始。