Предотвращение повторной отправки формы после нажатия кнопки

У меня есть проект Django, в котором есть несколько форм. Происходит следующее: когда я нажимаю кнопку submit 30 раз, мои данные вставляются в базу данных 30 раз. Я провел исследование и увидел много jquery или javascript решений в целом, но я не очень хорошо знаком с ними, поэтому я пытаюсь найти более питоническое / Django решение. Решение для фронтенда, которое работает для меня, было следующим:

<script type="text/javascript">
    var form = document.getElementById('post_form');
    var submitButton = document.getElementById('submit');
    form.addEventListener('submit', function () {
        submitButton.setAttribute('disabled', 'disabled');
        submitButton.value = 'Please wait...';
    }, false);
</script>

Вот мой код сейчас, и я надеялся найти способ заставить его работать без вышеуказанного:

просмотров:

@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>

модель:

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

Форма:

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

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

Я пробовал перенаправлять после form.save() и это успешно, но это не решает мою проблему с повторной отправкой. У меня была другая проблема с повторной отправкой при обновлении, и я решил ее с помощью сессий, но здесь я не уверен, как это сделать. Я должен повторить, что я понимаю, что существует решение на основе frontend javascript, но я хочу знать, можно ли это сделать на стороне сервера, а не клиента.

Вернуться на верх