代码之家  ›  专栏  ›  技术社区  ›  Johnny Wales

验证django 2中动态创建的modelform字段

  •  0
  • Johnny Wales  · 技术社区  · 8 年前

    我正在使用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')
                )
                )
    

    到目前为止,如果我在QuerySet中提交了任何文章,表单将根据需要进行验证和保存。

    实时站点中的文章将比在modelmultiplechoice字段中实际显示的文章多得多,因此我做了一些jquery,允许用户使用articlesearchbox替换modelmultiplechoice字段。这项工作非常出色,您可以搜索任何文章,包括那些不在原始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 %}
    

    问题: 如果我进行搜索并得到一篇不在原始queryset中的文章,则验证失败,并被告知这不是一个有效的选择。我需要一个验证器,允许任何一篇或多篇文章,只要它们在数据库中。

    我试过的: 我试着创建一个如下所示的验证器:

    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
    

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

    1 回复  |  直到 8 年前
        1
  •  1
  •   Fynn Becker    8 年前

    您的自定义验证器没有任何作用,因为它将被调用 之后 现场验证。有关在中运行订单验证的详细信息,请参阅 the django docs .

    相反,您可以通过继承django的multiplechoicefield来覆盖上述字段验证:

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

    你当然要用你的习惯 ArticleMultipleChoiceField 在你 StorylineAddArticleForm 对于 articles 字段。