向 Django 应用程序添加一个自定义的面向用户的表单(使用 selectize 和 taggit)

Posted

技术标签:

【中文标题】向 Django 应用程序添加一个自定义的面向用户的表单(使用 selectize 和 taggit)【英文标题】:Add a custom user-facing form to Django app (uses selectize and taggit) 【发布时间】:2016-05-21 15:40:40 【问题描述】:

我是 django 的新手,我正在尝试弄清楚如何使用 taggit-selectize 小部件(或 django-taggit)创建表单。我在网上找到的所有内容都是指它使用管理页面,但我希望标签面向用户且可编辑 - 就像我在这篇文章下面创建的标签一样。到目前为止,我已经确定我需要使用一个小部件来创建一个表单:

# models.py
from taggit_selectize.managers import TaggableManager
    tags = TaggableManager()

# forms.py
from taggit_selectize.widgets import TagSelectize
from .models import MyModel

class TagForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ('tags',)
        widgets = 'tags': TagSelectize(),

但我不知道如何在我的模板中包含此表单,以便它出现在我的MyModel 对象旁边。理想情况下,我想我希望它表现得像 django-fluent-comments,我可以打电话给 % render_comment_form for obj % 并收工。


更新

我编辑了views(见下文),现在可以访问模板中的表单,但我似乎无法提交我的标签(理想情况下,这也不会触发重定向)。

# views.py
from .forms import TagForm
def show_tags(request):
    return render(request, 'tags.html', 'tagform' : TagForm)

# tags.html        
<div>
 tagform.media 
 tagform.as_p 
</div>

【问题讨论】:

【参考方案1】:

所以,我终于想通了。它涉及将 tagform 包装在 &lt;form&gt; 标签中并捕获 POST 请求。作为记录,这是一个项目的一部分,该项目涉及使用 Haystack 返回我想要标记的结果列表。我的views.py 子类化了SearchView,而不是像我在此处定义的函数(show_tags()),而不是每页一个对象我有多个。

对于页面上的对象 obj,您有以下内容

# views.py
from .forms import TagForm
from .models import MyModel
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt

def show_tags(request):

    # Perhaps the request specifies the object, but
    # for simplicity's sake we just pick a specific model instance
    object = MyModel.objects.filter(pk = 123) 
    return render(request, 'tags.html', 'tagform' : TagForm,
                                         'obj' : MyModel)

@require_POST
@csrf_exempt
def create_tag(request):
    # See javascript below for creation of POST request
    data = request.POST
    tag_text_raw = data.get('tag_data')

    # clean_tag() not shown, but it splits the serialized
    # tag_text_raw and returns a list of strings
    tag_text_clean = clean_tag(tag_text_raw)

    obj_pk = data.get('obj_pk')

    #save tags to document
    doc = DocInfo.objects.get(pk = obj_pk)
    doc.tags.add(*tag_text_clean)

    # not strictly necessary; mainly for logging
    response_data = 'tag_text': tag_text_clean,
                 'obj_pk': obj_pk
                 

    return JsonResponse(response_data)

所以show_tags 使用render 将信息发送到模板,然后模板可以访问这些对象。这对我来说最初是没有意义的。

# tags.html (extends base.html)
% block scripts % block.super 
    <script type="text/javascript" src=" STATIC_URL js/ajaxtag.js"></script>
   tagform.media 
% endblock %    

 obj.text 
<form method="post" action="create_tag/" id="tag-form- obj.pk " name="tag-form-obj" data-object-id= obj.pk >
     tagform.as_p 
    <input type="submit" name ="tag-form-input" value="Add Tags" />
</form>

我们可以用javascript捕获POST请求:

    #ajaxtag.js
    (function($)
    
    // A stripped-down version of ajaxcomments.js from fluent_comments
    // See that file for further expansions
    $.fn.ready(function () 
        var tagform = $('form[name="tag-form-obj"]');

        if (tagform.length > 0) 
            // Detect last active input.
            // Submit if return is hit
            tagform.find(':input').focus(setActiveInput).mousedown(setActiveInput);
            tagform.submit(onTagFormSubmit);
        
    );

    function onTagFormSubmit(event)
       
        event.preventDefault();  // prevents redirect
        var form = event.target;

        create_tag(form);
        return false;
    

    function create_tag(form) 
    
        console.log("create_tag is working!") // sanity check
        var $form = $(form);
        var tag_text = $form.serialize();
        var url = $form.attr('action');
        var obj_id = $form.attr('data-object-id')

        $.ajax(
            url : url,
            type: "POST",
            data:  tag_data: tag_text, obj_pk: obj_id,

            success: function (data) 
                data;
                console.log(data);
                console.log('success');
            ,

            error: function (xhr, errmsg, err) 
                // Return error to console
                console.log(xhr.status + ": " + xhr.responseText)
            
        );

    

    function setActiveInput() 
        active_input = this.name;
    

    )(window.jQuery);

最后,urls.py 将请求发送回create_tag()

# urls.py
from .views import create_tag
...
url(r'^create_tag', create_tag, name = 'tag-form')
...

【讨论】:

以上是关于向 Django 应用程序添加一个自定义的面向用户的表单(使用 selectize 和 taggit)的主要内容,如果未能解决你的问题,请参考以下文章

向 admin auth 注册自定义用户模型

Django - 向用户授予自定义权限

Django Admin:向模板页面添加自定义字段

在管理界面上向 Django 内联对象添加自定义操作

添加自定义 Django 管理操作

向 Django Auth User 模型添加便利方法的最佳方法?