验证Django 2中动态创建的ModelForm字段

验证Django 2中动态创建的ModelForm字段,django,django-forms,Django,Django Forms,我使用的是Django 2.0,我有文章模型和故事情节模型。故事情节包含许多相关的文章 class Article(models.Model): headline_text = models.CharField(max_length=255, verbose_name='Headline') storylines = models.ManyToManyField(Storyline, verbose_name='Add to Storylines') 我有一个模型表单,可以让你

我使用的是Django 2.0,我有文章模型和故事情节模型。故事情节包含许多相关的文章

class Article(models.Model):
    headline_text = models.CharField(max_length=255, verbose_name='Headline')
    storylines = models.ManyToManyField(Storyline, verbose_name='Add to Storylines')
我有一个模型表单,可以让你选择一篇文章添加到故事情节中。该ModelForm类如下所示:

class StorylineAddArticleForm(forms.Form):
    articleSearchBox = forms.CharField(label="Search to narrow list below:")
    include_articles = [article.id for article in Article.objects.order_by('-sub_date')[:5]]
    articles = forms.ModelMultipleChoiceField(queryset=Article.objects.filter(id__in=include_articles).order_by('-sub_date'))
    def __init__(self, *args, **kwargs):
        super(StorylineAddArticleForm, self).__init__(*args, **kwargs)
        self.fields['articleSearchBox'].required = False
        self.helper = FormHelper(self)
        self.helper.layout = Layout(
            Field('articleSearchBox'),
            Field('articles'),
            ButtonHolder(
              Submit('submit', 'Add', css_class='button white')
            )
            )
def clean_article(self):
    art_ID = self.cleaned_data.get('articles', False)
    if(art_ID):
        try:
            art = Article.objects.get(pk=art_ID)
        except ObjectDoesNotExist:
            return None
    else:
        return None
    # if we are here, we have an article.
    return art
到目前为止,如果我在queryset中提交任何文章,表单将根据需要进行验证和保存

实时站点将有更多的文章显示在ModelMultipleEchoice字段中,因此我使用JQuery允许用户使用articleSearchBox替换ModelMultipleEchoice字段。这非常有效,您可以搜索任何文章,包括原始queryset中没有的文章。这是:

{% block content %}
<h2>Add Article</h2>
Add an existing article to <strong>{{ storyline.headline_text }}</strong>  storyline:<br>

Did you want to add <a href="{% url 'article:addnew_storyline' storyline.id %}">a new article</a> instead?<br>
<hr>
{% crispy form %}
{% endblock %}
{% block pagescripts %}
<script>
$(document).ready(function(){
  $("#id_articleSearchBox").on('input propertychange paste', function(){
      $.ajax({
        url:'/webproxy/a/?q=' + $("#id_articleSearchBox").val(),
        type:'get',
        dataType:'html',
        crossDomain:true,
        success:function(data)
       {
        $("#id_articles").empty().append(data);
       },
        error: function(data) {
            $("#id_articles").empty().append("<option value=\"-1\">No results</option>");
        }
    });
  }); // end article search box
});
</script>
{% endblock %}

这并没有改变行为。我一直在寻找一个验证器,它甚至可以允许任何值,或者只是检查它是否存在,但我运气不好

您的自定义验证器没有任何效果,因为它将在字段验证后被调用。有关在中运行订单验证的更多信息,请参阅

相反,您可以通过继承Django的MultipleChiceField来覆盖所述字段验证:

from django import forms


class ArticleMultipleChoiceField(forms.MultipleChoiceField):
    def validate(self, value):
        pass  # your custom validation

然后,您当然必须在
故事线ArticledArticleForm
中为
文章
字段使用自定义的
ArticleMultipleChieceField

这就成功了,现在我只需要找出如何用正确的初始值填充它。非常感谢。