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 client side thing; easily 'tamper-able')
What is the best way to do so in Django?
What I have tried?
I have not tried any yet, however, I've considered this options.
- Trigger a boolean field (where? on the form user submit or his/her account?) to change to True, then reset that field to False at midnight
With this approach, I wonder how I can reset the field to False at midnight too.
I asked the same question on Django Users, and a couple of suggestions have come in, so I'm looking into as well
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 = FormLastActivefields = '__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 belowif 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.userform1.save()form2.instance.created_by = request.userform2.save()return HttpResponseRedirect('/thanks/')else:form1 = GhanaECGForm(prefix='form1')form2 = FormLastActiveForm(prefix='form2')active = Noneif 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 contextelse:active = Falsereturn 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 forallowing 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.