I have created a "Subscribe" form using Wagtail form builder, with one email field that is required, I have also created a template tag to use this form in different places on the web site.
The problem:
If the user submits the form with an incomplete email address, I'll get a validation error (which is expected). However, if the user submits the form without providing an email address, wagtail sends the user to the actual form url and prompts the user to fill out the form again.
The behavior should be, that if the form is submitted without an email address, a validation error should be triggered as well, this is not happening.
Here is the form model code:
class FormField(AbstractFormField):
page = ParentalKey('SubscribeForm', related_name='form_fields')
class SubscribeForm(AbstractEmailForm):
intro = RichTextField(blank=True)
thank_you_text = RichTextField(blank=True)
content_panels = AbstractEmailForm.content_panels + [
FieldPanel('intro', classname="full"),
InlinePanel('form_fields', label="Form fields"),
FieldPanel('thank_you_text', classname="full"),
MultiFieldPanel([
FieldPanel('to_address', classname="full"),
FieldPanel('from_address', classname="full"),
FieldPanel('subject', classname="full"),
], "Email")
]
Here is the custom template tag code:
from django import template
from home.models import *
register = template.Library()
# Subscribe
#register.inclusion_tag('home/subscribe_form.html', takes_context=True)
def vdecristo_subscribe(context):
page = SubscribeForm.objects.get(slug='subscribase')
return {
'request': context['request'],
'page': page,
'form': page.get_form(),
}
Here is the html code:
{% load wagtailcore_tags vdecristo_tags %}
<!-- Callout Subscribe Form Green -->
<div class="shop-subscribe bg-color-green margin-bottom-40">
<div class="container">
<div class="row">
<div class="col-md-8 md-margin-bottom-20">
<h2>Subscribase para mantenerse<strong> informado</strong></h2>
</div>
<form action="{% pageurl page %}" method="POST">
{% csrf_token %}
<div class="col-md-4">
<div class="input-group">
<input id="id_subscribase" class="form-control" placeholder="Correo Electronico..." name="subscribase"
type="email">
<span class="input-group-btn">
<button class="btn" type="submit"><i class="fa fa-envelope-o"></i></button>
</span>
</form>
</div>
</div>
</div>
</div><!--/end container-->
</div>
Can somebody shed some light on this issue?
Hard to know without seeing your views.py code, but reloading the empty form is the kind of thing that happens when the if request.method == 'POST' ... portion of the view isn't receiving the request.POST form data.
Related
I am trying to handle login/registration functionality in a modal. I got successful login/registration working by importing the LoginForm and RegistrationForm into my modal view and then posting to the appropriate allauth URLs. The desired behavior is to have forms with errors rendered asynchronously in the modal.
I have not been able to get forms with errors (email doesn't exist when trying to login, passwords don't match when registering etc.) to render as an html partial in a modal with the errors. I'm not too sure where to start when trying to add this functionality into my own view/how to piggyback on the allauth views and change their functionality.
Adding the below to my views.py and url.py I've managed to get the allauth default template to load when the form is invalid (e.g. email field does not contain a valid email) but have not been able to get my template to load.
From views.py:
class LoginViewSnippet(LoginView):
success_url = reverse_lazy('home')
template_name = 'user_app/partials/loginmodal.html'
def get_context_data(self, **kwargs):
print('here1')
context = super(LoginView,self).get_context_data(**kwargs)
return context
def form_invalid(self, form):
print('here')
error_msg = 'error'
return HttpResponse(error_msg, status=400)
login = LoginViewSnippet.as_view()
From urls.py:
path('accounts/login',user_app_views.login, name='account_login'),
From user_app/partials/loginmodal.html:
...
<div class="modal-body">
<form id="loginform" method="POST" action="{% url 'account_login' %}" autocomplete="off">
{% csrf_token %}
{% for field in loginform %}
<div class="form-group mb-3">
{{ field.errors }}
{{ field | as_crispy_field }}
</div>
{% endfor %}
</form>
</div>
<div class="mx-auto">
<button form="loginform"type="submit" class="btn btn-success" hx-post="{% url 'account_login' %}" hx-target="#modals-here">Login</button>
<button type="button" class="btn btn-secondary" onclick="closeModal()">Close</button>
</div>
...
I am trying to add a subscribe to newsletter option on a django website. When a visitor enters
a valid email address it will be stored in the database. The subscription form is part of the base.html template.
All other templates of the website extend this template. I wish to implement this in a DRY way.
This is how I am trying to do it :
forms.py :
from dataclasses import fields
from django import forms
from . models import Subscribers, MailMessage
class SubcribersForm(forms.ModelForm):
class Meta:
model = Subscribers
fields = ['email', ]
views.py :
def base(request):
if request.method == 'POST':
form = SubcribersForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
form = SubcribersForm()
context = {'form': form}
return render(request, 'base.html', context)
The template: base.html
<form method = "POST" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>
models.py :
class Subscribers(models.Model):
email = models.EmailField(null=True)
date = models.DateTimeField(auto_now_add=True)
def __str__self(self):
return self.email
In the backend, I can see that the Subscribers table has been created. However, when I enter any email address from the home
page and click subscribe button it does not store it in the database. What could be the issue here?
It could be that you have no action declared in your form. Assuming you have a url like this:
path('add-subscriber/', base, name='base'),
...your form would need a way to call it upon submit, like this:
<form method = "POST" action="{% url 'base' %}" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>
Here is what i have in base.html (inside the footer, so this newsletter form will be in every page)
<form action="" method="POST">
{% csrf_token %}
<div class="form-group">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder='Enter email address' onfocus="this.placeholder = ''" onblur="this.placeholder = 'Enter email address'">
<div class="input-group-append">
<button class="btn" type="submit"><span class="lnr lnr-arrow-right"></span></button>
</div>
</div>
</div>
</form>
Here is the model (subscribe/models.py)
class Subscriber(models.Model):
email = models.EmailField()
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.email
what i have in views.py
def subscribe_form(request):
if request.method == 'POST':
email = request.POST.get('email')
new_email = Subscriber()
new_email.email = email
new_email.save()
return redirect('home-page')
here is urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.PostListView.as_view(), name='home-page'),
path('subscribe/', views.subscribe_form, name='subscriber'),
path('archive/', views.archive, name='archive-page'),
path('category/', views.category, name='category-page'),
path('contact/', views.contact, name='contact-page')
]
after submitting the submit button i'm getting this error in shell
Method Not Allowed (POST): /
Method Not Allowed: /
[18/Jan/2020 04:13:11] "POST / HTTP/1.1" 405 0
so, i'm a beginner, im trying to build a blog, but i didn't find any useful solution that can solve this issue. maybe i'm going totally wrong, but anyway if someone can help me to make this working.
Thank you all.
In your index URL, you are not allowed to post.So change it to subscribe/
<form action="{% url 'subscriber' %}" method="POST>
I am trying to use 2 post method in a single page one is for login and other one is for contact us
login is working fine but after submitting contact us the content of login and contact us page is gone
I tried to pass various type of dictionary but still, it's not working
app/views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from homePage.forms import SignInForm,DropUsaMessage
# Create your views here.
def homePage(request):
if request.method == 'POST' and 'SignIn' in request.POST:
sign_in_detail = SignInForm(request.POST)
if sign_in_detail.is_valid():
return render(request, "index2.html",{})
elif request.method == 'POST' and 'SendMessage' in request.POST:
message_detail = DropUsaMessage(request.POST)
if message_detail.is_valid():
return render(request, "index.html",{})
else:
sign_in_detail = SignInForm()
message_detail = DropUsaMessage()
context={
"form":sign_in_detail,
"forms":message_detail
}
return render(request, "index.html",context)
index.html
<div class="container contact-form">
<form method="post">
<h3>Drop Us a Message</h3>
{% csrf_token %}
{{ forms }}<br><br>
<div class="form-group">
<input type="submit" name="SendMessage" class="btnContact" value="Send Message" />
</div>
</form>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-8">
<img src="{% static 'img/sampleImage.jpg' %}" width="100%" height="100%" class="d-inline-block align-top" alt="">
</div>
<div class="col-md-4">
<form method="POST">
{% csrf_token %}
{{ form }}
<div class="form-check">
<span class="fpswd">Forgot password?</span>
</div>
<button type="submit" class="btn btn-primary" name="SignIn">Submit</button>
</form>
</div>
</div>
</div>
app/forms.py
from django import forms
from django.core import validators
class SignInForm(forms.Form):
email=forms.EmailField(widget=forms.EmailInput(attrs={"class": 'form-control',"placeholder":'Enter E-mail',"id": 'exampleInputEmail1'}))
password=forms.CharField(widget=forms.PasswordInput(attrs={"class":'form-control',"placeholder":'Enter Password',"id":'exampleInputPassword1'}))
class DropUsaMessage(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={"class":'form-control',"placeholder":'Your Name'}))
email = forms.EmailField(widget=forms.EmailInput(attrs={"class": 'form-control',"placeholder":'Your E-mail',"id": 'exampleInputEmail1'}))
phone = forms.IntegerField(widget=forms.NumberInput(attrs={"class":'form-control',"placeholder":'Your Phone Number'}))
message = forms.CharField(widget=forms.Textarea(attrs={"class":'form-control',"placeholder":'Type Your Message',"style":'width:100%; height: 150px'}))
Expected Result:
After filling up the contact us form the field will be there.
Actual result:
there is no field in Contact us(except Send Message button) and no field in SignInForm(no e-mail and no password).
Just follow the code flow and you'll notice that in the case of a POST request and "SignIn" in the post, you return the rendered "index2.html" template without any context (form and forms will be undefined in your template). Idem for the other case:
return render(request, "index2.html", {}) # empty context
Worse, if the form posted is not valid, you'll notice you only define one for the forms and not the other one, so when the code execution reaches the line context = {"form": ..., "forms": ...}, one of them will be undefined and your view will "crash", return a 500 error.
context = {'form': sign_in_detail, # sign_in_detail never defined for second "if"
'forms': message_detail} # message_detail never define for first "if"
In general, when a POST is successful, you should always redirect to another view (or the same view). That's the internet convention, in order to avoid page reload issues that would resubmit the same data. Do this:
return redirect('home') # or whatever your homepage url pattern is called
Also, it would make more sense to post your forms to different views (change the action attribute of each of your <form> tags) so you can process them in separate views which is cleaner code:
<form action="{% url 'create_message' %}" method="post">
in Django I make a form which get an email address and save it in database and this my form.py:
class NewsletterUserSignUpForm(forms.ModelForm):
class Meta:
model = NewsletterUsers
fields = ['email']
def clean_email(self):
email = self.cleaned_data.get('email')
return email
and this is my views.py :
def newsletter_signup(request):
form = NewsletterUserSignUpForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
if NewsletterUsers.objects.filter(email=instance.email).exists():
messages.warning(request, 'Your Email Already Exist In Our DataBase.',
'alert alert-warning alert-dismissible')
else:
instance.save()
messages.success(request, 'Your Has Been Submitted To Our DataBase.',
'alert alert-success alert-dismissible')
context = {
'form': form,
}
return render(request, 'newsletter/subscribe.html', context)
the problem is here that this form has it own input which the input must put inside it but I want to design my own template and get input in my template then pass it to this form and my question is how do I can pass inputs in my .html template file to my form?
this is my html file and don't know to put what in href for input tag :
<form method="post" class="login100-form validate-form">
{% csrf_token %}
<span class="login100-form-title p-b-43">
Subscribe
</span>
<div>
<inputtype="email" name="Email">
<span class="label">Email</span>
</div>
<button type="submit" href="">
Subscribe
</button>
</div>
and what should I put in my href and how pass input to form from here?
In addition, I'm sorry for writing mistakes in my question.
From what I understand, you want to create your own custom input box and when that box is filled, you want the form input box to also get filled.
Hide the form input box using display:none.
Create your own custom input box, use javascript to fill the form input box when custom input box is filled.
Ex :
<script>
form_input_box = document.getElementById('id_of_form_input_box')
custom_input_box = documen.getElementById('id_of_custom_input_box')
$("id_of_custom_input_box").change(function(){
form_input_box.value = custom_input_box.value
});
</script>
the problem it was for my html code, I Should add an id and name attribute to my input tag and use this id and name for getting input from html and pass it to my form, and for href attribute I write the url that redirect to my form.
fixed html code:
<form method="post" class="login100-form validate-form">
{% csrf_token %}
<span class="login100-form-title p-b-43">
Subscribe
</span>
<div class="wrap-input100 container-login100-form-btn rs1 rs2 validate-input padding-50"
data-validate="Username is required">
<input id="email" maxlength="100" class="input100" type="email" name="email">
<span class="label-input100">Email</span>
</div>
<div class="container-login100-form-btn">
<button type="submit" href="{% url 'newsletter_subscribe' %}" class="login100-form-btn">
Subscribe
</button>
</div>
<div class="text-center w-full p-t-23">
<a style="font-size: 15px" href="{% url 'newsletter_unsubscribe' %}" class="txt1">
Click Here To Unsubscribe.
</a>
</div>
</form>