You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django表单重复提交问题:寻求Python/服务端解决方案

解决Django表单重复提交的服务端方案需求

问题背景

我有一个Django项目,包含若干表单,当前遇到的问题是多次点击提交按钮时,数据会被多次插入数据库。我知道有很多jQuery/JavaScript前端解决方案,但不熟悉这类技术,希望找到更Pythonic/Django风格的服务端解决方案。

已找到的前端可行方案

var form = document.getElementById('post_form');
var submitButton = document.getElementById('submit');
form.addEventListener('submit', function () {
    submitButton.setAttribute('disabled', 'disabled');
    submitButton.value = 'Please wait...';
}, false);

当前项目代码

Views代码

@method_decorator(login_required(login_url='index', redirect_field_name=None), name='dispatch')
class CreatePostView(views.FormView):
    model = Post
    form_class = CreatePostForm
    template_name = 'posts/create_post.html'

    def form_valid(self, form):
        post = form.save(commit=False)
        post.user = self.request.user
        post.save()
        return redirect('index')

Template代码

<form action="{% url 'create post' %}" method="POST" enctype="multipart/form-data">
    {{ form.as_p }}
    {% csrf_token %}
    <p>
        <button type="submit" class="btn btn-secondary">Submit</button>
    </p>
</form>

Model代码

class Post(models.Model):
    MAX_TITLE_LENGTH = 20
    MIN_TITLE_LENGTH = 3
    MAX_DESTINATION_LENGTH = 30
    MIN_DESTINATION_LENGTH = 3
    MAX_DESCRIPTION_LENGTH = 550
    MIN_DESCRIPTION_LENGTH = 5

    title = models.CharField(
        max_length=MAX_TITLE_LENGTH,
        validators=(MinLengthValidator(MIN_TITLE_LENGTH), name_and_title_validator),
        error_messages={
            'max_length': f'Post title must be a maximum of {MAX_TITLE_LENGTH} characters.',
            'min_length': f'Post title must be at least {MIN_TITLE_LENGTH} characters long.',
        },
        null=False,
        blank=False,
    )

    photo = CloudinaryField(
        folder='mediafiles/post_photos',
        public_id=get_photo_name_by_post_name,
        null=False,
        blank=False,
    )

    destination = models.CharField(
        max_length=MAX_DESTINATION_LENGTH,
        validators=(MinLengthValidator(MIN_DESTINATION_LENGTH), ),
        error_messages={
            'max_length': f'Destination must be a maximum of {MAX_DESTINATION_LENGTH} characters.',
            'min_length': f'Destination must be at least {MIN_DESTINATION_LENGTH} characters long.',
        },
        null=False,
        blank=False,
    )

    description = models.CharField(
        max_length=MAX_DESCRIPTION_LENGTH,
        validators=(MinLengthValidator(MIN_DESCRIPTION_LENGTH), ),
        error_messages={
            'max_length': f'Description must be a maximum of {MAX_DESCRIPTION_LENGTH} characters.',
            'min_length': f'Description must be at least {MIN_DESCRIPTION_LENGTH} characters long.',
        },
        null=False,
        blank=False,
    )

    category = models.ForeignKey(
        PostCategory,
        on_delete=models.CASCADE,
        default='',
        null=False,
        blank=False,
    )

    user = models.ForeignKey(
        UserModel,
        on_delete=models.CASCADE,
        null=False,
        blank=True,
    )

    def __str__(self):
        return self.title

Form代码

class CreatePostForm(AddPlaceholdersFormMixin, RemoveLabelsFormMixin, AddStyleClassFormMixin, forms.ModelForm):
    class Meta:
        model = Post
        exclude = ('user', )
        labels = {
            'category': 'CHOOSE A CONTINENT',
        }

        widgets = {
            'description': forms.Textarea(),
        }

已尝试的方法及困惑

  • 已在form.save()后执行重定向,但无法解决重复提交问题
  • 之前用session解决过刷新导致的重复提交问题,但不知道如何用同样思路解决多次点击提交按钮的问题
  • 明确需求:不使用前端方案,仅通过服务端解决该问题

内容的提问来源于stack exchange,提问作者Elena Konstantinova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:11:06