Render a form function in multiple django templates - django

I have written a function where the function captures the details from a form and sends an email after form submission. How can I have this functionality rendered to multiple django templates where i can call the form and do so.
Below is the related function..
def emailView(request):
if request.method == 'GET':
form = myform()
else:
form = myform(request.POST)
if form.is_valid():
subject='form Details'
mobile = form.cleaned_data['mobile']
email = form.cleaned_data['email']
dummy = '\nMobile: '+mobile+'\nEmail: '+email'
try:
send_mail(subject, dummy, 'dummy#gmail.com', ['dummy1#gmail.com', 'dummy2#gmail.com'])
messages.success( request, " Thank you !! For contacting.')
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('email')
return render(request, "my_app/email.html", {'form': form})

You can use include tag to do so. Try out the below way.
consider the below as your url in urls.py
path('your_form/', views.emailView, name='myform'),
you can call your function any number of templates using the below tag.
#template1.html
<form method="post" action="{% url 'myform' %}">
{% include 'yourapp/email.html' %}
<button type="submit">Submit</button>
#template2.html
<form method="post" action="{% url 'myform' %}">
{% include 'yourapp/email.html' %}
<button type="submit">Submit</button>

Related

In Django, how can we stop losing the details filled in the form, if it fails validation?

I am using the UserCreationForm for user registration in my Django web app. When the user fills in the detail (username, password, confirm_password) and submits, then if the form fails validation (maybe because username already exists or password don't match or password is too short) then the user is redirected back to the register page.
Now my problem is that when he is redirected back to the register page, the form is blank again, i.e. he has to start all over again, which is not a good user experience because his form might fail one or more times.
I want that if the form fails validation and when he is redirected to the registration form, he should see his previously filled in details so that he can just correct the field which is causing the error and move on. Is there any way the data can be retained?
Here is my code of the register function in views.py:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST or None)
if form.is_valid():
# some code
return redirect('login')
else:
messages.error(request, form.errors)
return HttpResponseRedirect(reverse("register"))
else:
return render(request, 'accounts/register.html')
my register.html:
<form method="POST" action="{% url 'register' %}">
{% csrf_token %}
<input name="username" type="text" class="..." style="...">
<input name="password1" type="password" class="..." style="...">
<input name="password2" type="password" class="..." style="...">
<button type="submit">Sign up</button>
</form>
Edit:
I have not passed the form in context to the template, so that I can control the CSS of my input fields, which I am not sure how to do otherwise without creating forms.py file separately.
If it's not possible to retain details in the form, then what should I do to at least improve the present situation?
Instead of return redirect just render the response with the form object again:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST or None)
if form.is_valid():
# some code
return redirect('login')
messages.error(request, form.errors)
else:
form = UserCreationForm()
return render(request, 'accounts/register.html', {'form': form})
In the template since you want to control css use django-widget-tweaks:
{% load widget_tweaks %}
<form method="POST" action="{% url 'register' %}">
{% csrf_token %}
{% render_field form.username class="..." style="..." %}
{% render_field form.password1 class="..." style="..." %}
{% render_field form.password2 class="..." style="..." %}
<button type="submit">Sign up</button>
</form>
The load widget tweaks must be at the top of the html file like all load tags.
def register(request):
context = {}
if request.method == 'POST':
form = UserCreationForm(request.POST or None)
if form.is_valid():
# some code
return redirect('login')
else:
context['form'] = form
messages.error(request, form.errors)
context['form'] = UserCreationForm()
return render(request, 'accounts/register.html', context)
it should work

{ % include tag %} including only one object from another template

guys i need a small help
here is my views.py
def signup(request):
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
verification=VerificationForm(request.POST)
if form.is_valid():
userObj = form.cleaned_data
username = userObj['username']
email = userObj['email']
password = userObj['password']
return HttpResponseRedirect('/index/verification/')
# if
if not (User.objects.filter(username=username).exists() or User.objects.filter(email=email).exists()):
User.objects.create_user(username, email, password)
user = authenticate(username = username, password = password)
login(request, user)
return HttpResponseRedirect('/')
else:
raise forms.ValidationError('Looks like a username with that email or password already exists')
else:
raise forms.ValidationError('a valid')
else:
form = UserRegistrationForm()
verification = VerificationForm()
return render(request, 'question/signup.html',context= {'verification':verification,'form' : form})
here you can see i have declared two context variables one is form and the other one is verification now i want to use
now this is my signup.html
{% extends 'question/index.html '%}
{% block body_block %}
<div class="conrainer">
<form method="POST">
{% csrf_token %} {{ form.as_p }}
<button type="submit">Submit</button>
</form>
facebook auth
</div>
{% endblock %}
now i have used form variable in this page
and i want to use verification varible in another page as django views are not made to use two templates in a single view
after searching a lot in online forums i came to know about {% include tag %}
after trying to use that tag after going through documentation
this is how my verification.html is
{% include 'question/signup.html' with obj=verification only%}
<div class="container">
<form method="post">{% csrf_token %}
<p>{{verification.as_p}}</p>
<p>{{obj.as_p}}</p>
<input type="submit" name="verify" value="" action='.' align='center'name='submit'>
</form>
</div>
here is my urls.py file
urlpatterns = [
# url(r'^/',views.home,name='home'),
url(r'^home/',Home,name='home'),
url(r'^ques/',Create.as_view(success_url="/index/home/"),name='ques'),
url(r'^signup/',signup,name='signup'),
# url(r'^signup/',MyFormView.as_view(),name='signup'),
url(r'^verification/',TemplateView.as_view(template_name="question/verification.html")),
url(r'^logout/$', auth_views.logout,name='logout'),
url(r'^search/',Search,name='search'),
url(r'^accounts/', include('allauth.urls')),
# url(r'^verify/',verificationView,name='signup'),
# CreateView.as_view(model=myModel, success_url=reverse('success-url'))
]
but after trying it so many ways either obj or verification shows up in the site is there any way where i can only get the context object instead of getting the subit button and all from my signup.html using INCLUDE any kind of help is appreciated

Django form error:local variable 'context' referenced before assignment

I'm collecting data from form, processing data(right now I'm not) and displaying the result on the same HTML page from where the user submits the form.
Here is my views.py file:
def index(request):
template = 'predictor/index.html'
if request.method =='POST':
form = EvalForm(request.POST)
if form.is_valid():
text ='thank you for submitting form'
else:
text='something wrong.'
context: {
'text':text,
}
return render(request,template,context)
else:
form = EvalForm()
return render(request,template)
Here is my index.html file
<form method="POST" action="{% url 'predictor' %}">
{% csrf_token %}
//all input fields including submit button here
</form>
<div class="result">
{{ text }}
</div>
All other things like urls are configured properly.
What I'm doing wrong here?
You have typo in your code.
Should be context = {'text':text,} instead of context: {'text':text,}.

django view redirects to URL it shouldn't

I have the following view
def edit_booking(request, pk=None):
if not request.user.is_authenticated:
raise Http404
agent = Agent.objects.get(user=request.user)
booking = get_object_or_404(Booking, pk=pk)
form = BookingForm(request.POST or None, instance=booking)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return HttpResponseRedirect(instance.get_absolute_url())
elif form.errors:
messages.error(request,"There was a problem, please try again")
context = {
"form": form,
}
return render(request,'booking_form.html', context)
I use the following urls.py
urlpatterns = [
url(r'^booking/create', create_booking, name="create-booking"),
url(r'^booking/$', booking_list, name="booking-list"),
url(r'^booking/(?P<pk>\d+)/$', booking_detail, name="booking-detail"),
url(r'^booking/(?P<pk>\d+)/edit', edit_booking, name="edit-booking"),
]
For some reason when I try to submit the form after editing some booking (e.g. http://127.0.0.1:8000/booking/24/edit) I am automatically redirected to (http://127.0.0.1:8000/booking/24/).
As far as I can tell django is not processing any further code in the view. I tried to figure out with simple print("something") to see where in the code it ends up but it just goes to the url right away as soon as I submit from the template. For completeness sake this is the template:
{% extends 'base.html' %}
<div class="col-sm-6 col-sm-offset 3">
{% block content %}
<form method="POST" action=".">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save"/>
</form>
{% endblock %}
</div>
".", which you used as the action of the form, is interpreted by browsers as "the base of the current path directory". Since you have not used a trailing slash in your /edit URL, the browser submits the form to the nearest base, ie /booking/24.
You should always use a trailing slash:
url(r'^booking/create/$', create_booking, name="create-booking"),
url(r'^booking/$', booking_list, name="booking-list"),
url(r'^booking/(?P<pk>\d+)/$', booking_detail, name="booking-detail"),
url(r'^booking/(?P<pk>\d+)/edit/$', edit_booking, name="edit-booking"),
You need to check for the request method otherwise it will redirect on initial form rendering because django uses the same view for initial rendering and submitting the form.
if request.method == 'POST':
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return HttpResponseRedirect(instance.get_absolute_url())
elif form.errors:
messages.error(request,"There was a problem, please try again")
else:
context = {
"form": form,
}
return render(request,'booking_form.html', context)

Invalid form when uploading a file

I am trying a basic example in uploading a file with django.
I tried the code from the django documentaion but I keep getting invalid form. And when I don't test the validation of the form and try to handle the file directly, I get:
MultiValueDictKeyError at /neurons/nblast
"
'file'"
P.S:
Previously, I had used a model with a FileField and set the (upload_to), but in my current case I don't need to use the model, I only need to let the user uploads his files.
This is my code:
Template
<body>
<form action="" method="post">
{{ form }}
<br>
<button class="btn btn-success" name="btn_upload">
<span class="glyphicon glyphicon-upload"></span>
<b>Upload</b>
</button>
{% csrf_token %}
</form>
</body>
Views
def test(request):
if request.method == GET:
form = UploadFileForm()
if request.method == POST:
if 'btn_upload' in request.POST:
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
else:
print 'Not Valid'
form = UploadFileForm()
return render_to_response('test.html',
{'form': form},
context_instance=RequestContext(request))
Forms:
class UploadFileForm(forms.Form):
file = forms.FileField()
Thank you very much
Have you tried looking at The Django 'File Uploads' docs , especially the enctype="multipart/form-data" attribute?
u missed this one enctype="multipart/form-data"