如何在不刷新页面的情况下使用 django-crispy-forms 实现引导模式表单

Posted

技术标签:

【中文标题】如何在不刷新页面的情况下使用 django-crispy-forms 实现引导模式表单【英文标题】:How do I implement bootstrap modal forms with django-crispy-forms, without page refresh 【发布时间】:2020-04-17 10:41:45 【问题描述】:

我一直在尝试使用 django-crispy forms 在引导模式中实现一个表单。我正在使用基于类的视图。我知道我需要一些 Ajax,但我并不理解我所看到的所有示例。 我试过 django-bootstrap-modal-forms - 这适用于模态,但遗憾的是,它不支持引导样式,我找不到任何添加它的方法。当我尝试使用引导程序表单类 form-control 将引导程序样式添加到 django-bootstrap-modal-forms 时,表单不会提交,并且没有给出错误。 所以现在,我想回到 django-crispy-forms

所以我的问题是:

    如何使用 django-crispy-forms

    实现引导模式表单

    如何使用 ajax 实现验证,以避免页面重新加载 - 错误也应该具有与 django-crispy-forms 相同的错误样式

      另外,当对象已成功添加到数据库中时,如何使用警报实现成功消息。

我的代码如下所示:

my_template.html 这目前包含 django-bootstrap-modal-forms 的 CSS 类。查看https://pypi.org/project/django-bootstrap-modal-forms/ 您可以将模态正文中的文本替换为 form |脆 使用 django-crispy-forms

<form method="post" action="">
  % csrf_token %

 <div class="modal-header">
    <h5 class="modal-title">Create new Task</h5>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">

    % for field in form %
      <div class="form-group% if field.errors % invalid% endif %">
        <label for=" field.id_for_label "> field.label </label>
         field 
        % for error in field.errors %
          <p class="help-block invalid-feedback"><strong> error </strong></p>
        % endfor %
      </div>
    % endfor %
  </div>

  <div class="modal-footer">
    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    <button type="button" class="submit-btn btn btn-primary">Add Task</button>
  </div>

</form>

javascript

        $(document).ready(function() 

            $(".create-task").modalForm(
                formURL: "% url 'create_task' %"
            );

        );

forms.py

from .models import Task, Categories
from bootstrap_datepicker_plus import DateTimePickerInput
from django import forms
from django.db.models import Q
from bootstrap_modal_forms.forms import BSModalForm
from django.contrib.auth import get_user_model

class TaskForm(BSModalForm):
    # Get al the categories from the database
    categories_queryset = Categories.objects.all()

    task_title = forms.CharField(max_length=100)
    task_description = forms.CharField(widget=forms.Textarea)        
    due_date = forms.DateTimeField(
        widget = DateTimePickerInput(format='%Y-%m-%d %H:%M')
    )    
    is_completed = forms.BooleanField()
    categories = forms.ModelChoiceField(categories_queryset, empty_label="---None---")
    #parent = forms.ModelChoiceField()

    #task_title.widget.attrs.update('class': 'form-control')


    class Meta:
        model = Task
        fields = ['task_title', 'task_description', 'due_date', 'is_completed', 'categories', 'parent']

    def __init__(self, *args, **kwargs):
        super(TaskForm, self).__init__(*args, **kwargs)
# I have errors using the Queryset to find entities with Categories.user_id == null, and Categories.user_id=get_user_model() -- It gives an error about unpacking boolean.
        #self.fields['categories_queryset'] = Categories.objects.filter(Categories.user_id=get_user_model())
        # Q(Categories.user_id__isnull==True) |
        # User.objects.filter(username=username).exists():

models.py

from django.db import models
from django.db.models import Q
from users.models import CustomUser
from django.urls import reverse
from django.contrib.auth import get_user_model


class Categories(models.Model):
    category_type = models.CharField(max_length=50)
    user = models.ForeignKey(CustomUser, null = True,  on_delete=models.CASCADE)

    def __str__(self):
        return '%s ' % (self.category_type)

    def get_absolute_url(self):
        return reverse('task_list')

class Task(models.Model):
    task_title = models.CharField(max_length=100)
    task_description = models.TextField()
    date_added =  models.DateTimeField(auto_now_add=True)
    due_date  = models.DateTimeField()
    is_completed = models.BooleanField(default=False)
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)

    categories = models.ForeignKey(Categories, on_delete=models.CASCADE)
    parent = models.ForeignKey("self", on_delete=models.CASCADE)

    class Meta:
        verbose_name = "Task"
        verbose_name_plural = "Tasks"         

    def __str__(self):
        return '%s ID: %s' % (self.task_title, self.last_name)

    def get_absolute_url(self):
        return reverse('task_detail')        

谢谢...

【问题讨论】:

【参考方案1】:

花了很长时间才弄清楚,但幸运的是解决方案非常简单。

ajax 请求在您的示例中按预期工作。但是,django-modal-forms 会使用这一行检查响应是否有错误:

if ($(response).find(settings.errorClass).length > 0) ...

默认设置中的错误类设置为“.invalid”,但脆的表单会使用“.is-invalid”类呈现错误。这就是为什么表单不会被识别为错误并提交(包括页面刷新)而不是重新呈现错误消息的原因。

javascript 部分更改为以下内容为我解决了问题。

$(document).ready(function() 
    $(".create-task").modalForm(
        formURL: "% url 'create_task' %",
        errorClass: ".is-invalid"
     );
);

【讨论】:

【参考方案2】:

这个问题发布了很长时间,但由于我目前遇到同样的问题,我敢于分享我的经验: 当我不像你那样使用脆皮形式时,我已经按预期运行了。我担心,您必须处理 JS 实现,如 django-crispy-forms 文档中所述。

【讨论】:

以上是关于如何在不刷新页面的情况下使用 django-crispy-forms 实现引导模式表单的主要内容,如果未能解决你的问题,请参考以下文章

Django:如何在不刷新页面的情况下更新图像?

如何使用 jQuery 在不刷新页面的情况下更新 cookie 值?

如何在不刷新页面的情况下更新角度数据?

如何在不重新加载整个页面的情况下刷新 div?

如何在不刷新页面的情况下显示错误?

如何在不刷新页面的情况下使用 ajax 保存 acf_form