Django:如何使用ModelFormSet和FormWizard过滤ForeignKey选项(例如使用request.user)?

时间:2013-09-02 07:19:25

标签: django django-users django-1.5 django-forms django-formwizard

ModelForm中有几个ForeignKeys,我想在modelformset_factory的表单向导中使用(不是100%确定formset)我想知道如何限制下拉字段的选择因为我需要动态地做。我想通过编写自己的modelformset工厂来尝试它,但是在stackoverflow上我读到了其他方法,但不幸的是我不理解它们。

那是我走了多远:

models.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 https://stackoverflow.com/a/4858044/2704544 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
#######################################################################################

link来源)

views.py

# This is from https://stackoverflow.com/a/623198/2704544 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)
        #...

link来源)

urls.py

#...
url(r'^register/$', views.RegWizard.as_view(views.reg_wiz_forms), name='register'),
#...

我还read关于curry和其他内容,并试图覆盖get_initkwargsWizardView的其他方法,但我找不到任何更多的文档或提示话题。也许有人可以帮助我。

更新

它现在部分用curry。部分原因是它不适用于管理功能:

views.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)])

我得到一个AttributeError:“'function'对象没有属性'base_fields'”这听起来像是同一个问题here

但是,当我覆盖WizardView的{​​{1}}并直接在url.py中调用它时,它会起作用:

get_form_list

现在我想知道是否有一个没有覆盖该方法的解决方案。

1 个答案:

答案 0 :(得分:3)

您只需要将Model上的attendee属性的外键查询集作为ModelForm上的过滤属性。你在这里是正确的:

self.fields['attendee'].queryset = Person.objects.filter(owner=user)

这假设Person类中存在属性“owner”。

然而,这不起作用,因为你的用户arg在哪里或什么?一种解决方案是,如您所述,将表单 init 方法包含在内,以包含正确的用户对象:

    form = staticmethod(curry(AttendeeForm, user=<the-user-obj>))

现在,您从 init 方法中的kwargs弹出用户arg:

user = kwargs.pop('user')

现在,您过滤的查询集只会显示您过滤的人物。

def __init__(self, user, *args, **kwargs): I tried this but I didn't get 
it to work.

上面的行不会因为多种原因而起作用,主要是它永远不会从任何地方调用,你在那里创建一个新函数,而不是覆盖现有函数,这就是我们正在做的事情。 init 方法。

关于设计的一些可能有用的建议 - 你在这里有许多线程都提供了许多不同的想法,使事情复杂化很多。尝试将您的问题过滤到基本概念。在这里,它是数据问题的表示,所以考虑从表单开始,这就是它的用途。 :-)