yof*_*fee 1 django django-forms django-formwizard django-users django-1.5
在一间几ForeignKeys ModelForm,我想在窗体向导与使用modelformset_factory(不是100%肯定该formset),我不知道如何限制下拉场的选择,因为我需要动态地做到这一点。我想通过编写自己的模型集工厂来尝试它,但是在 stackoverflow 上我阅读了其他方法,但不幸的是我不理解它们。
那是我走了多远:
模型.py
#...
class Attendee(models.Model):
"""Event specific attendee details."""
# event is set by URL.
event = models.ForeignKey(Event)
attendee = models.ForeignKey(Person) # Contact details, should be limited to user
accommodation = models.ForeignKey(Accommodation, blank=True) # *
workshop = models.ForeignKey(Workshop, blank=True) # *
volunteer = models.ForeignKey(Volunteer, blank=True) # *
# *= should be limited to event but I think I will be able to handle that.
#...
class AttendeeForm(forms.ModelForm):
class Meta:
model = Attendee
def __init__(self, *args, **kwargs):
# def __init__(self, user, *args, **kwargs): I tried this but I didn't get
# it to work.
super(AttendeeForm, self).__init__(*args, **kwargs)
# self.fields['attendee'].queryset = Person.objects.filter(owner=user)
self.fields['workshop'].required = True
#...
# This is from /sf/answers/340063111/ but I don't understand it. ##
def form_setup(**kwargs):
def make_form(data, prefix=None, initial=None):
form = (data, prefix, initial)
for k, v in kwargs.items():
if k == 'some_list':
form.fields['some_list'].choices = v # What does that mean?
...
return form
return make_form
#######################################################################################
Run Code Online (Sandbox Code Playgroud)
(链接到源)
视图.py
# This is from /sf/answers/43623891/ but I don't understand it. ###
class Callback(object):
def __init__(self, field_name, aff):
self._field_name = field_name
self._aff = aff # What is this aff?
def cb(self, field, **kwargs):
nf = field.formfield(**kwargs)
if field.name == self._field_name: # this is 'options' field
nf.queryset = ServiceOption.objects.filter(affiliate=self._aff)
return nf
#######################################################################################
reg_wiz_forms = (
('attendees', modelformset_factory(Attendee, form=AttendeeForm, exclude='event',
# formfield_callback=Callback('option', affiliate).cb Just copied. Why can you call
# cb without arguments?
)),)
class RegWizard(SessionWizardView):
def get_form_instance(self, step):
instance = None
if step == '0':
instance = Attendees.objects.filter(owner__owner=self.request.user)
#...
Run Code Online (Sandbox Code Playgroud)
(链接到源)
网址.py
#...
url(r'^register/$', views.RegWizard.as_view(views.reg_wiz_forms), name='register'),
#...
Run Code Online (Sandbox Code Playgroud)
我还阅读了curry其他内容并尝试覆盖get_initkwargs和其他方法,WizardView但我找不到关于该主题的更多文档或提示。也许有人可以帮助我。
它curry现在部分起作用。部分原因是它不适用于管理功能:
视图.py
def manage_wizard(request, event):
AttendeeFormSet = modelformset_factory(Attendee, form=AttendeeForm, exclude='event')
AttendeeFormSet.form = staticmethod(curry(AttendeeForm, user=request.user))
wiz = RegWizard
wiz.event = event
return wiz.as_view([('attendees', AttendeeFormSet)])
Run Code Online (Sandbox Code Playgroud)
我得到一个 AttributeError: "'function' object has no attribute 'base_fields'" 这在这里听起来像同样的问题。
但是当我覆盖WizardView'sget_form_list并直接在 url.py 中调用它时,它可以工作:
reg_wiz_forms = ('attendees', modelformset_factory(Attendee, form=AttendeeForm, exclude='event'))
class RegWizard(SessionWizardView):
def get_form_list(self):
self.form_list['attendees'].form = staticmethod(curry(AttendeeForm, user=self.request.user))
return super(RegWizard, self).get_form_list()
Run Code Online (Sandbox Code Playgroud)
现在我想知道是否有不覆盖该方法的解决方案。
您只需要将 Model 上的参加者属性的外键查询集设置为 ModelForm 上的过滤器。你在这里是正确的:
self.fields['attendee'].queryset = Person.objects.filter(owner=user)
Run Code Online (Sandbox Code Playgroud)
这是假设 Person 类上存在属性“所有者”。
但是,这不起作用,因为您的用户 arg 在哪里或什么?一种解决方案是柯里化表单init方法,正如您所提到的,以包含正确的用户对象:
form = staticmethod(curry(AttendeeForm, user=<the-user-obj>))
Run Code Online (Sandbox Code Playgroud)
现在您从init方法中的 kwargs 中弹出您的用户 arg :
user = kwargs.pop('user')
Run Code Online (Sandbox Code Playgroud)
现在您过滤的查询集将只显示您过滤的人员。
def __init__(self, user, *args, **kwargs): I tried this but I didn't get
it to work.
Run Code Online (Sandbox Code Playgroud)
由于多种原因,上面的行将不起作用,主要是它永远不会从任何地方调用,您正在那里创建一个新函数,而不是覆盖现有的函数,这就是我们在覆盖init方法时所做的。
只是一些关于设计的可能有用的建议 - 这里有很多线程,它们都提供了许多不同的想法,使事情复杂化了很多。尝试将您的问题过滤到基本概念。在这里,它是数据问题的演示文稿,因此请考虑从表单开始,这就是它的用途。:-)