根据已记录的用户(一种特定于对象的权限),我已覆盖模型的默认管理器,以便仅显示允许的项目:
class User_manager(models.Manager):
def get_query_set(self):
""" Filter results according to logged user """
#Compose a filter dictionary with current user (stored in a middleware method)
user_filter = middleware.get_user_filter()
return super(User_manager, self).get_query_set().filter(**user_filter)
class Foo(models.Model):
objects = User_manager()
...
通过这种方式,每当我使用Foo.objects
时,都会检索当前用户并将过滤器应用于默认查询集,以便仅显示允许的记录。
然后,我有一个带有ForeignKey to Foo的模型:
class Bar(models.Model):
foo = models.ForeignKey(Foo)
class BarForm(form.ModelForm):
class Meta:
model = Bar
当我编写BarForm时,我希望只看到filteres Foo实例,但不应用过滤器。我认为这是因为在没有用户登录且没有应用过滤器的情况下,在Django启动时评估和缓存查询集。
有没有一种方法可以让Django在运行时评估ModelChoice查询集,而不必在表单定义中明确它? (尽管存在所有性能问题......)
修改 我发现了查询集的评估位置(django \ db \ models \ fields \ related.py:887):
def formfield(self, **kwargs):
db = kwargs.pop('using', None)
defaults = {
'form_class': forms.ModelChoiceField,
'queryset': self.rel.to._default_manager.using(db).complex_filter(self.rel.limit_choices_to),
'to_field_name': self.rel.field_name,
}
defaults.update(kwargs)
return super(ForeignKey, self).formfield(**defaults)
任何提示?
答案 0 :(得分:2)
确实存在这个问题 - 需要使用组中的用户对象填充选择表单,但fun_vit的答案不正确(至少对于django 1.5而言)
首先,你不想覆盖字段['somefield']。choices对象 - 它是一个ModelChoiceIterator对象,而不是一个查询集。其次,django.forms.BaseForm中的注释会警告您不要覆盖base_fields:
# The base_fields class attribute is the *class-wide* definition of
# fields. Because a particular *instance* of the class might want to
# alter self.fields, we create self.fields here by copying base_fields.
# Instances should always modify self.fields; they should not modify
# self.base_fields.
这对我有用(django 1.5):
class MyForm(ModelForm):
users = ModelMultipleChoiceField(queryset=User.objects.none())
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args,**kwargs)
site = Site.objects.get_current()
self.fields['users'].queryset = site.user_group.user_set.all()
class Meta:
model = MyModel
答案 1 :(得分:1)
我使用自定义表单的 init :
class BT_Form(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BT_Form, self).__init__(*args, **kwargs)
#prepare new values
cities = [(u'',u'------')] #default value
cities.extend([
(
c.pk,
c.__unicode__()
) for c in City.objects.filter(enabled=True).all()
])
self.fields['fly_from_city'].choices = cities #renew values
答案 2 :(得分:0)
没办法:我必须重写queryset定义(在启动时评估)