我遇到了一个小问题,我认为这个问题很常见。 这里描述的问题非常通用:
class Ownable(models.Model):
user = models.ForeignKey(django.contrib.auth.models.User)
class Meta:
abstract = True
class Bowl(Ownable):
pass
class Pea(Ownable):
bowl = models.ForeignKey(bowl)
关系是:User [1:n] Bowl
,
User [1:n] Pea
Bowl [1:n] Pea
现在,当我想要创建新的Pea
时,我还需要将其分配给Bowl
,如下所示:
def create_new_pea(request):
PeaFrom = inlineformset_factory(django.contrib.auth.models.User, Pea)
return render(request, 'app/pea/create.html', {'formset': PeaFrom()})
我在这个过程中如何能够将QuerySet
传递给bowl
字段,因为用户只能将bean放入他自己的碗中。
我很高兴收到建议。我尝试为formset-factory创建自定义表单,但我需要request
实例来了解当前用户。
答案 0 :(得分:3)
一种简单的方法是在实例化formset后执行此操作。
def create_new_pea(request):
PeaFormset = inlineformset_factory(django.contrib.auth.models.User, Pea)
formset = PeaFormset(instance=request.user)
for form in formset:
form.fields['bowl'].queryset = request.user.bowl_set.all()
return render(request, 'app/pea/create.html', {'formset': formset}
我认为可以将此行为构建到自定义Formset
类中,从而覆盖_construct_forms
方法:
class UserLimitedFormset(BaseInlineFormset):
def _construct_forms(self):
super(UserLimitedFormset, self)._construct_forms()
for form in self:
form.fields['bowl'].queryset = self.instance.bowl_set.all()
PeaFormset = inlineformset_factory(django.contrib.auth.models.User, Pea, formset=UserLimitedFormset)
要使用回调,我认为在创建formset之前,您需要一个闭包或functools.partial
来记录用户。可能是这个,虽然它没有经过测试,我在封口上生锈了:
def create_new_pea(request):
user = request.user
def set_queryset(f, **kwargs):
formfield = f.formfield(**kwargs)
if f.name == 'bowl':
formfield.queryset = user.bowl_set.all()
return formfield
PeaFormset = inlineformset_factory(django.contrib.auth.models.User, Pea, formfield_callback=set_queryset)
答案 1 :(得分:1)
不需要那么复杂 - 只需在表单初始化中添加一个kwarg'person'。我将这种新形式称为PeaForm,因为你列出的PeaForm实际上是Formset类型。
class PeaForm(ModelForm):
def __init__(self, *args, **kwargs):
person = kwargs.pop('person')
super(PeaForm, self).__init__(*args, **kwargs)
qs = Bowl.objects.filter(user=person)
self.fields['bowl'].queryset = qs
class Meta():
model = Pea
当您在工厂中使用它时,您只需要在制作表单时讨论该方法:
from django.utils.functional import curry
person = request.user
PeaFormset = inlineformset_factory(django.contrib.auth.models.User, Pea, form=PeaForm)
PeaFormSet.form = staticmethod(curry(PeaForm, person=person))
现在只有属于用户的碗才会出现在PeaForm的QS中。