Django:使用get_form_kwarg将url参数传递到ModelChoiceField选择过滤器的表单__in



我正在构建一个常见问题解答应用程序。

模型流程主题->章节->文章。

Article有一个到Section的FK, Section有一个到Topic的FK。

在我的创建文章中,我想要在Topic_Pk中,所以当用户选择一个Section时,选择的选择仅限于Topic下附加的Sections。

我使用get_from_kwarg将Topic_Pk从url传递到表单中的__init__。我一直得到一个TypeError __init__() got an unexpected keyword argument 'topic_pk'。我不想在__init__参数中弹出数据或设置topic_pk=None,因为这会使整个点无效。

我缺少什么来允许我使用这个变量?

Url:

url(r'^ironfaq/(?P<topic_pk>d+)/article/create$', ArticleCreateView.as_view()),

视图:

class ArticleCreateView(CreateView):
    model = Article
    form_class = CreateArticleForm
    template_name = "faq/form_create.html"
    success_url = "/ironfaq"
    def get_form_kwargs(self):
        kwargs = super(ArticleCreateView,self).get_form_kwargs()
        kwargs.update(self.kwargs)
        return kwargs

形式:

class CreateArticleForm(forms.ModelForm):
    section = forms.ModelChoiceField(queryset=Section.objects.none())
    def __init__(self, *args, **kwargs):
        super(CreateArticleForm, self).__init__(*args, **kwargs)
        self.fields['section'].queryset = Section.objects.filter(topic_pk=self.kwargs['topic_pk'])
    class Meta:
        model = Article
        widgets = {
            'answer': forms.Textarea(attrs={'data-provide': 'markdown', 'data-iconlibrary': 'fa'}),
        }
        fields = ('title','section','answer')

模型:

class Article(Audit):
    title = models.CharField(max_length=255)
    sort = models.SmallIntegerField()
    slug = models.SlugField()
    section = models.ForeignKey(Section,on_delete=models.CASCADE)
    answer = models.TextField()
    vote_up = models.IntegerField()
    vote_down = models.IntegerField()
    view_count = models.IntegerField(default=0)
    class Meta:
        verbose_name_plural = "articles"
    def __str__(self):
        return self.title
    def total_votes(self):
        return self.vote_up + self.vote_down
    def percent_yes(self):
        return (float(self.vote_up) / self.total_votes()) * 100
    def get_absolute_url(self):
        return ('faq-article-detail',(), {'topic__slug': self.section.topic.slug,
            'section__slug': self.section.slug, 'slug': self.slug})

对于当前的__init__签名,在调用super()之前,必须从kwargs中弹出topic_pk,否则您将获得TypeError

在你的问题中,你说弹出值会"使整个点无效",但我认为你错了。调用super()后,仍然可以使用topic_pk的值。

class CreateArticleForm(forms.ModelForm):
    section = forms.ModelChoiceField(queryset=Section.objects.none())
    def __init__(self, *args, **kwargs):
        topic_pk = kwargs.pop('topic_pk')
        super(CreateArticleForm, self).__init__(*args, **kwargs)
        self.fields['section'].queryset = Section.objects.filter(topic_pk=topic_pk)

另一种方法是使用topic_pk作为命名参数。注意,这会改变__init__方法的签名,因此它可能会破坏其他代码(例如,如果您在其他地方有CreateArticleForm(request.POST))。

    def __init__(self, topic_pk=None, *args, **kwargs):
        super(CreateArticleForm, self).__init__(*args, **kwargs)
        self.fields['section'].queryset = Section.objects.filter(topic_pk=topic_pk)

最新更新