Skip to content Skip to sidebar Skip to footer

Allow Form Submission Only Once A Day Django

I want to allow users to submit a django form once, and only once everyday. After submitting the form, the form wouldn't even show (server-side checkings, I don't want to use JS or

Solution 1:

Its been a while, since I asked this question, and I figured a way (bad way, maybe) to get it done. Here's how

#forms.py
class FormLastActiveForm(forms.ModelForm):
    class Meta:
        model = FormLastActive
        fields = '__all__'

# Create a model form for MyModel model below here

#models.py
class FormLastActive(models.Model):
    created_by = models.ForeignKey(User, blank=True, null=True)

class MyModel(models.Model):
    name = models.CharField(max_length=300)
    remark = models.CharField(max_length=300)

#views.py
schedule.every().day.at("00:00").do(reset_formlastactive) # will explain this in a bit too
def homepage(request):
    schedule.run_pending() # will explain this in a bit below
    if request.method == 'POST':
        form1 = MyModelForm(request.POST, prefix='form1', user=request.user)
        form2 = FormLastActiveForm(request.POST, prefix='form2')
        if form1.is_valid() and form2.is_valid():
            form1.instance.created_by = request.user
            form1.save()
            form2.instance.created_by = request.user
            form2.save()
            return HttpResponseRedirect('/thanks/')
    else:
        form1 = GhanaECGForm(prefix='form1')
        form2 = FormLastActiveForm(prefix='form2')

    active = None
    if request.user.is_authenticated():
        form_is_active = FormLastActive.objects.filter(created_by=request.user).exists()
        if is_active:
            active = True #if there exist a record for user in context
        else:
            active = False

    return render(request, 'index.html', {
            'first_form': form1,
            'second_form': form2,
            'no_form': active, # this triggers display of entire form or not
            }
        )


# index.html
<form action="." method="POST">
    {% csrf_token %} 
    {% form form=first_form %} {% endform %} # Using material package for form styling. Could use {{ first_form.as_p }} too for default styling.
    <!-- {% form form=second_form %} {% endform %} # This part is intentionally hidden to the user, and doesn't show up in the template -->
    <input type="submit" href="#" value="Submit" />
</form>

Upon submitting, the hidden form and and the visible form all get submitted, and are processed in the views.py above.

Since users are allowed to submit one form per day, then it means there need to be a means to reset the FormLastActive model at midnight, to give every user a fresh start. This reset for all happens whenever the first person makes a request after 12 midnight every day.

Here's how that approach ties in:

# the function for resetting FormLastActive Model every midnight
def reset_formlastactive():
    '''Resets the database responsible for
        allowing form submissions'''
    x = FormLastActive.objects.all()
    x.delete()

schedule.every().day.at("00:00").do(reset_formlastactive)
# if you noticed, this came just before the `homepage()` function begun in the views.py. This set the stage for resetting everyday, at 00:00 GMT.

To actually do the resetting, we need to call the above function, and we do so via:

schedule.run_pending()

as seen just below the homepage() function in the views.py

The run_pending() is used, so that even if the time to reset is passed, and the homepage() hasn't been run after 12 midnight, whenever that happens, the run_pending() will ensure every backlog resetting is done.

I'm currently using this approach at logecg.khophi.co

I hope there's a better, cleaner and reusable way of doing this, but in the mean time, this works!.

I hope to this question I asked doesn't deserve the downvotes after all. Wished django had an inbuilt feature of this for all types of forms.


Solution 2:

You need to add information to your User class so that it contains the last time a form was submitted.

In the function that renders the form and accepts the post, you can check that the user did not submit a form in the current day. If he did, you render an error view for GET instead of the true form, and you generate an error in case of POST request.

When the POST is validated and fully accepted, you update the date information in the User class.


Post a Comment for "Allow Form Submission Only Once A Day Django"