Related
--PROBLEM--
I have created a basic calculator using Django.
The app takes some basic form inputs before executing some calculations and returning the outcomes to the user, however I want the user's inputs to remain visible in the form on submission.
At present the followin experience occurs.
User enters values into form and submits using 'Calculate' button.
Results are returned as expected but form and values are no longer present.
User can press 'Calculate' button to return to start of process and blank form.
--DESIRED OUTCOME--
--CODE--
forms.py
from django import forms
class InvestmentForm(forms.Form):
starting_amount = forms.FloatField()
number_of_years = forms.FloatField()
return_rate = forms.FloatField()
annual_additional_contribution = forms.FloatField()
views.py
from django.shortcuts import render
from django.views import View
from .forms import InvestmentForm
class Index(View):
def get(self, request):
form = InvestmentForm()
return render(request, 'loancalculator/index.html', {'form': form})
def post(self, request):
form = InvestmentForm(request.POST)
if form.is_valid():
total_result = form.cleaned_data['starting_amount']
total_interest = 0
yearly_results = {}
for i in range(1, int(form.cleaned_data['number_of_years'] +1)):
yearly_results[i] = {}
# CALCULATE THE INTEREST
interest = total_result * (form.cleaned_data['return_rate'] / 100)
total_result += interest
total_interest += interest
# ADDITIONAL CONTRIBUTION
total_result += form.cleaned_data['annual_additional_contribution']
# SET YEARLY RESULTS
yearly_results[i]['interest'] = round(total_interest, 2)
yearly_results[i]['total'] = round(total_result,2)
# CREATE CONTEXT
context = {
'total_result': round(total_result,2),
'yearly_results': yearly_results,
'number_of_years': int(form.cleaned_data['number_of_years'])
}
# RENDER THE TEMPLATE
return render(request, 'loancalculator/index.html', context)
else:
form = InvestmentForm()
return render(request, 'loancalculator/index.html', {'form':form})
index.html
{% extends 'loancalculator/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="row justify-content-center">
<div class="col-4 border bg-light">
<div class="row t-5">
<div class="col-12 col-md-6 mx-md-auto">
<h1> Investment Calculator</h1>
<h5> Enter the details below to see your estimate</h5>
<form action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" type="submit">Calculate</button>
</form>
<br>
</div>
</div>
</div>
<div class="col-4 border">
<div class="row t-5">
<div class="col-12 col-md-6 mx-md-auto">
<h1>Investment Results</h1>
<h3> After {{ number_of_years }} years, your investment is worth ${{ total_result }}</h3>
<div class="mt-5">
<table class="table">
<thead>
<tr>
<th scope="col">Year</th>
<th scope="col">Interest</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
{% for key, value in yearly_results.items %}
<tr>
<th scope="row">{{ key }}</th>
<td>{{ value.interest }}</td>
<td>{{ value.total }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
Two ways you can go about doing what you want as I see it:
Method 1
Use sessions to hold the data and then refeed it to the form using initial form values. This is probably the easiest since it most closely matches what you already have.
class Index(View):
def get(self, request):
# Fill in the initial values on the unbound form:
initial = {
'starting_amount': request.session.get('starting_amount'),
'number_of_years': request.session.get('number_of_years'),
'return_rate': request.session.get('return_rate'),
'annual_additional_contribution': request.session.get('annual_additional_contribution'),
}
form = InvestmentForm(initial=initial)
return render(request, 'home/index.html', {'form': form})
def post(self, request):
form = InvestmentForm(request.POST)
if form.is_valid():
# After getting the cleaned_data, set a session variable to hold it
total_result = form.cleaned_data['starting_amount']
request.session['starting_amount'] = total_result
number_of_years = int(form.cleaned_data['number_of_years'])
request.session['number_of_years'] = number_of_years
return_rate = form.cleaned_data['return_rate']
request.session['return_rate'] = return_rate
annual_additional_contribution = form.cleaned_data['annual_additional_contribution']
request.session['annual_additional_contribution'] = annual_additional_contribution
total_interest = 0
yearly_results = {}
for i in range(1, number_of_years +1):
yearly_results[i] = {}
# CALCULATE THE INTEREST
interest = total_result * (return_rate / 100)
total_result += interest
total_interest += interest
# ADDITIONAL CONTRIBUTION
total_result += annual_additional_contribution
# SET YEARLY RESULTS
yearly_results[i]['interest'] = round(total_interest, 2)
yearly_results[i]['total'] = round(total_result,2)
# CREATE CONTEXT
context = {
# CHANGED: pass the 'form' to the context!
'form': form,
'total_result': round(total_result,2),
'yearly_results': yearly_results,
'number_of_years': number_of_years
}
# RENDER THE TEMPLATE
return render(request, 'home/index.html', context)
else:
form = InvestmentForm()
return render(request, 'home/index.html', {'form':form})
Method 2
From what you show here, anyway, you could just use JavaScript to do the calculations by grabbing the values directly from the DOM after they are entered, doing the calculations on the front end with JavaScript, and then fill in the values by targeting the locations where you want the results displayed in the DOM. No need for forms, no reloading of pages.
When you create the context, the value 'form' doesn't get set (views.py, under get())
Here I am using Django 3.0 and Python 3.7
In my Django template When using forms my submit is not triggering and no action is not performing
Here is my views.py
def sendmail(request):
company={}
form = JobEmailDataForm()
client = request.user.client
client_id = request.user.client.id
email_data = JobEmailData.objects.filter(client_id=client)
for i in email_data:
reminderstatus = i.reminder_status
bookingstatus = i.booking_today_status
purchasing_officer = i.purchasing_officer
bookedby = request.user
client_data = Client.objects.filter(id=client_id)
for val in client_data:
company['name']=val.name
company['phone']=val.phone
company['email']=val.email
company['replay_to_email']=val.replay_to_email or ''
company['website']=val.website
company['logo'] = val.logo_url
company['address'] = get_client_address(client)
return render(request, 'core/job_email_form_1.html', locals())
Here is my forms.py
class JobEmailDataForm(forms.Form):
name = forms.CharField(max_length=100, label='Company Name', widget=forms.TextInput(attrs={'class':'input-xlarge'}))
address = forms.CharField(max_length=256, label='Company Address', widget=forms.TextInput(attrs={'class':'input-xlarge'}))
phone = forms.CharField(max_length=100, label='Company Phone', widget=Html5TelephoneInput(attrs={'class':'input-xlarge'}))
website = forms.URLField(max_length=100, label='Company Website', required=False, widget=forms.TextInput(attrs={'class':'input-xlarge'}))
email = forms.EmailField(label='Company Email', widget=Html5EmailInput(attrs={'class':'input-xlarge'}))
replay_to_email = forms.EmailField(label='Send from Email (Optional)', required=False, widget=Html5EmailInput(attrs={'class':'input-xlarge'}))
purchasing_officer = forms.EmailField(label='Purchasing Officer Email', required=False, widget=Html5EmailInput(attrs={'class':'input-xlarge'}))
logo = forms.ImageField(label='Image', required=False)
confirmation = forms.CharField(max_length=256, label='Additional Booking Confirmation Message', widget=forms.Textarea)
amendments = forms.CharField(max_length=256, label='Additional Booking Amendments Message', widget=forms.Textarea)
cancellation = forms.CharField(max_length=256, label='Additional Booking Cancellation Message', widget=forms.Textarea)
booking_today = forms.CharField(max_length=256, label='Additional Booking today Message', widget=forms.Textarea)
reminder = forms.CharField(max_length=256, label='Additional Booking Reminders Message', widget=forms.Textarea)
reminder_status = forms.ChoiceField(choices=REMINDER_CHOICES,label='Reminders Message Settings',)
booking_today_status = forms.ChoiceField(choices=REMINDER_CHOICES,label='Booking Today Message Settings',)
class Meta:
widgets = {
"confirmation": forms.TextInput,
}
fields = ['name', 'address', 'phone', 'website','email', 'replay_to_email' , 'logo','confirmation','amendments','cancellation','reminder','is_email_customer','is_email_user','reminder_status']
Here is my job_email.html
<div class="row">
<div class="span6 offset1">
<!-- START non-filtered -->
<form method="post" enctype="multipart/form-data" action="/saveemaildata/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<fieldset class="add">
<br><br>
{% for field in form.visible_fields %}
<div class="control-group">
<label class="control-label pull-left" for="{{ field.auto_id }}">{{ field.label }}</label>
<div class="controls" style="margin-left: 0px;">
{{ field }} {% if field.label == 'Send from Email (Optional)' %}{% if client.email_validated_status == 'processed' or client.email_validated_status == 'Approved by client' %} Processed Check now {% elif client.email_validated_status == 'Validated' %} ValidatedCheck now {% elif client.email_validated_status == 'Pending' %} Validate - Check how {% endif %}{% endif %}
</div>
<p>{{ field.help_text }}</p>
</div>
{% endfor %}
</fieldset>
<div id="form-buttons-container" class="form-actions">
<div class="controls">
<input type="submit" class="btn btn-inverse" value="Update JobEmails">
<a class="btn btn-default" href="{% url "roles_list" %}">Cancel</a>
{% if role %}
<a class="btn btn-danger" href="{% url "roles_delete" role.pk %}">Delete role</a>
{% endif %}
</div> <!--/form-actions-->
</div>
</form>
.....
.....
.....
</div> <!-- /row -->
Here my submit button is not working I couldn't understand where I am wrong
Here is my urls.py
re_path(r'^saveemaildata/$',savejob,name='save_email_data'),
Here is my saveemail view.py
def savejob(request):
messages = []
client = request.user.client
if request.POST:
companyName = request.POST['name']
companyAddress = request.POST['address']
companyPhone = request.POST['phone']
companyWebsite = request.POST['website']
companyEmail = request.POST['email']
replay_to_email = request.POST['replay_to_email']
purchasing_officer = request.POST['purchasing_officer']
Confirmation = request.POST['confirmation']
Amendments = request.POST['amendments']
Cancellation = request.POST['cancellation']
Reminder = request.POST['reminder']
Bookingtoday = request.POST['booking_today']
reminder_status = request.POST['reminder_status']
booking_today_status = request.POST['booking_today_status']
client_id = ClientUser.objects.filter(id=request.user.id)[0].client_id
doc = Client.objects.get(id=client_id)
errors = []
import sys, traceback
if replay_to_email:
if doc.replay_to_email != replay_to_email:
doc.email_validated_status = 'Pending'
send_email_validate.delay(request.user, 1)
doc.name = companyName
doc.replay_to_email = replay_to_email
doc.email = companyEmail
doc.phone = companyPhone
doc.website = companyWebsite
if 'logo' in request.FILES:
doc.logo_url = request.FILES['logo']
print("DOC LOGO URL IS",doc.logo_url)
doc.logo_url.storage = S3Boto3Storage(bucket_name='lightdegree')
print("DOC LOGO URLLL",doc.logo_url.storage)
else:
errors.append("There is no document specified")
doc.save()
template = 'core/savejob.html'
objclient = Client.objects.get(name=companyName,email=companyEmail)
clientid = objclient.id
email_data = JobEmailData.objects.filter(client_id=clientid)
if not email_data:
objemail = JobEmailData(name = companyName,phone=companyPhone,
website=companyWebsite,client_id=clientid,
address=companyAddress,
confirmation=Confirmation,amendments=Amendments,
cancellation=Cancellation,reminder=Reminder,booking_today=Bookingtoday,
purchasing_officer=purchasing_officer,reminder_status=reminder_status,booking_today_status=booking_today_status)
objemail.save()
else:
objemail = JobEmailData.objects.filter(client_id=clientid).update(name = companyName,phone=companyPhone,
website=companyWebsite,
address=companyAddress,
confirmation=Confirmation,amendments=Amendments,
cancellation=Cancellation,reminder=Reminder,booking_today=Bookingtoday,
purchasing_officer=purchasing_officer,reminder_status=reminder_status,booking_today_status=booking_today_status)
messages.append('Job emails successfully updated')
return HttpResponseRedirect('/admin/job_emails/')
How can i make my submit button to work and where i am wrong
Sorry for the late reply. I think you're missing the form tag.
Template of a minimal HTML form (django):
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
Let me know if it worked out! It does for me :)
I have two request function in views one is with .get method and the other one with .post. Both of the function works properly because in the the terminal the code is 200.
[01/Apr/2021 08:04:39] "GET /search/search HTTP/1.1" 200 4164
[01/Apr/2021 08:04:57] "POST /search/search HTTP/1.1" 200 4164
The problem comes when i try to render the function with .post method to the html template nothing appear on the html page.
def wind_search(request):
if request.method == 'post':
city = request.post['city']
weather_city_url = urllib.request.urlopen('api.openweathermap.org/data/2.5/weather?q=' + city + '&appid=1a7c2a40a0734d1dc18141fc6b6241bb').read()
list_of_data = json.loads(waether_city_url)
# main wind information
wind_speed = list_of_data['wind']['speed']
# wind_gust = wea['current']['wind_gust']
wind_deg = list_of_data['wind']['deg']
# wind conversiont m/s to knots
def wind_converter(w):
knots = 2
kt = (float(w)) * knots
return kt
wind_response = wind_converter(wind_speed)
#convert wind degree in cardinal direction.
def degrees_to_cardinal(d):
dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
ix = round(d / (360. / len(dirs)))
return dirs[ix % len(dirs)]
direction = degrees_to_cardinal(wind_deg)
wind_data = {
"wind_response":wind_response,
"wind_direction":direction,
}
else:
wind_data={}
context = {"wind_data":wind_data}
return render(request, 'API/wind_search.html',context)
This is the html template:
{% extends "API/base.html" %}
{% block content %}
<!--Jumbotron -->
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-4">Wind search</h1>
<p class="lead">Write the city and check th wind condition. </p>
<!-- form input search tool -->
<nav class="navbar navbar-expand-lg navbar-dark">
<form method="post" class="col-md"">
{% csrf_token %}
<div class=" input-group">
<input type="text" class="form-control" name="city" placeholder="Choose Your City ...">
<div class="input-group-btn">
<button type="submit" class="btn btn-primary">Search</button>
</div>
</div>
</form>
</nav>
<div class="row">
{% if wind_response and wind_direction %}
<h4><span>Wind Speed :</span> {{wind_data.wind_speed}}</h4>
<h4><span>Wind_Direction :</span> {{wind_data.wind_direction}}</h4>
</div>
{% endif %}
</div>
{% endblock content %}
I think the problem is with the html because basically the view don't show any error message, so i tried to change couple of time the html code but without success. Any help/ explenation is nice.
Thank you very much.
Please set the render and redirect template,
def wind_search(request):
if request.method == 'POST':
#this block of code manages if there is a POST request...
city = request.POST.get('city')
weather_city_url = urllib.request.urlopen('api.openweathermap.org/data/2.5/weather?q=' + city + '&appid=1a7c2a40a0734d1dc18141fc6b6241bb').read()
list_of_data = json.loads(waether_city_url)
# main wind information
wind_speed = list_of_data['wind']['speed']
# wind_gust = wea['current']['wind_gust']
wind_deg = list_of_data['wind']['deg']
# wind conversiont m/s to knots
def wind_converter(w):
knots = 2
kt = (float(w)) * knots
return kt
wind_response = wind_converter(wind_speed)
#convert wind degree in cardinal direction.
def degrees_to_cardinal(d):
dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
ix = round(d / (360. / len(dirs)))
return dirs[ix % len(dirs)]
direction = degrees_to_cardinal(wind_deg)
wind_data = {
"wind_response":wind_response,
"wind_direction":direction,
}
# the page that you want to load after submitting your POST request <-----------------------------------------------------
return redirect( 'redirect to a view ' )
#the below block of code will cater for the GET method request
else:
wind_data={
'foo' : 'foo'
}
#the page you want to render on a Get Request <-----------------------------------------------------
return render(request,'render the required html for GET request' , wind_data)
I have a list of entries which are displayed in a webpage. Each entry has the same input form. But my problem arises when data is put into the input form, it appears on every single one of them. How do I change this.
Each input form is treated as a single cloned entity distributed over many entries.
views.py
def topic(request, topic_id, type): #
topic = Topic.objects.get(id = topic_id, type = 't_topic')
entries = topic.entry_set.order_by('-date_added')
images = Image.objects.filter(imgtopic__in = entries)
ArticleFormSet = formset_factory(CheckAnswer, extra = 2)
if request.method == 'POST':
formset = ArticleFormSet(request.POST)
if form.is_valid():
return HttpResponseRedirect(reverse('learning_logs:index'))
else:
formset = ArticleFormSet()
context = {'topic': topic, 'entries': entries, 'images': images, 'formset': formset}
return render(request, 'learning_logs/topic.html', context)
topic.html template
{%load staticfiles %}
{% block content %}
{% for entry in entries(n) %}
<div class = 'secondary-container'>
<li>
<div class = 'date'>
<p >{{ entry.date_added|date:'M d, Y H:i'}}</p>
</div>
{%include 'learning_logs/view_files.html'%}
<div class = 'video-container'>
{%include 'learning_logs/video.html' %}
</div>
<div class = 'entry-text'>
<p>{{ entry.text|linebreaks }}</p>
<p>$ {{entry.price_set.get.ptext}}</p>
</div>
</li>
<li>
<p> Enter Answer: </p>
<form action = "{%url 'learning_logs:topic' topic.id topic.type%}" method = 'post'>
{{formset.management_form}}
<table>
{% for form in formset%}
{{form.as_p}}
{% csrf_token %}
<button name = "submit">Submit answer</button>
{% endfor %}
</table>
</form>
</div>
forms.py
class CheckAnswer(forms.Form):
your_answer = forms.CharField(label = "Enter Your Key", max_length = 100)
def clean(self):
cleaned_data=super(CheckAnswer, self).clean()
your_answer = cleaned_data.get("your_answer")
try:
p = Keys.objects.get(key = your_answer)
except Keys.DoesNotExist:
raise forms.ValidationError("Incorrect code.")
My new problem is that I can't separate the forms into the different lists. Since extra = 2, I get 2 instances of forms on the same entry list.
I tried using the {%for form in formset%} command in the topic.html template to give each entry a form, but I get an of ['ManagementForm data is missing or has been tampered with'] when I click submit.
Image of the problem
I was figuring how to reuse the same registration form and view on multiple templates and pages, and in different formats. E.g. on the page, in a modal etc. I am however some trouble in figuring out the best practice for solving this problem. One thing I am actively trying to avoid is repeating myself, but I can't seem to find a solution that is satisfying enough.
At the moment I have one central view that handles user registrations that looks like this. At the moment it can only handle to output one form on the signup_form template, but I want to extend that to the index page and be able to be outputted in a modal as well.
Views.py
def signup(request):
template_name = 'core/authentication/signup_form.html'
custom_error_list = []
if request.method == "POST":
form = SignUpForm(request.POST)
if form.is_valid():
#Check for duplciate email
email = form.cleaned_data.get('email')
username = form.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).exists():
custom_error_list.append("A user with that email already exists")
else:
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
subject = 'Activate your StockPy Account'
sender = '' #Insert sender address here
message = render_to_string('core/authentication/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user)
})
user.email_user(subject, message)
return redirect('authentication:account_activation_sent')
else:
form = SignUpForm()
return render(request, template_name, {'form': form, 'custom_error_list': custom_error_list})
#Activate the user as he/she clicks the email verification link which lead to tihs view
def activate(request, uidb64, token):
try:
#Using a [:1] is ad-hoc solution to get rid of the starting 'b' symbol
uid = force_text(urlsafe_base64_decode(uidb64[1:]))
user = User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.profile.email_confirmed = True
user.save()
login(request, user)
return redirect(template_name)
else:
return render(request, 'core/authentication/account_activation_invalid.html')
forms.py
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django import forms
class LoginForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email','password']
class SignUpForm(UserCreationForm):
email = forms.EmailField(max_length=254, widget=forms.TextInput(attrs={'placeholder': 'Email...', 'class' : 'form-control', 'pattern' : '[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,3}$'}))
class Meta:
model = User
fields = ['email', 'username', 'password1', 'password2']
def __init__(self, *args, **kwargs):
super(SignUpForm, self).__init__(*args, **kwargs)
self.fields['username'].widget = forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Username...',
})
self.fields['password1'].widget = forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Password...',
'type': 'password',
})
self.fields['password2'].widget = forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Password again...',
'type': 'password',
})
My signup form currently looks like this.
signup_form.html
{% extends 'base.html' %}
{% load static %}
<!-- End Navbar -->
{% block page-header %}
<div class="section section-signup" style="background-image: url({% static 'core/assets/img/bg8.jpg' %}); background-size: cover; background-position: top center; min-height: 700px;">
<div class="container">
<div class="row">
<div class="card card-signup" data-background-color="orange">
<form class="form" method="POST" action="">
{% csrf_token %}
<div class="header text-center">
<h4 class="title title-up">Sign Up</h4>
<div class="social-line">
<a href="#twitter" class="btn btn-neutral btn-twitter btn-icon btn btn-round">
<i class="fa fa-twitter"></i>
</a>
<a href="#facebook" class="btn btn-neutral btn-facebook btn-icon btn-lg btn-round">
<i class="fa fa-facebook-square"></i>
</a>
<a href="#google" class="btn btn-neutral btn-google btn-icon btn-round">
<i class="fa fa-google-plus"></i>
</a>
</div>
</div>
<div class="card-body">
<!-- Output error messages -->
{% for field in form %}
<div style="color:red; list-decorations:none;" class="text-center">
{{ field.errors.as_text }}
</div>
{% endfor %}
{% for error in custom_error_list %}
<div style="color:red;" class="text-center">
* {{ error }}
</div>
{% endfor %}
<!-- Output all fields -->
{% for field in form %}
<div class="input-group form-group-no-border">
<span class="input-group-addon">
<i class="now-ui-icons
{% if field.name == 'email' %} ui-1_email-85{% endif %}
{% if field.name == 'username' %} users_circle-08{% endif %}
{% if field.name == 'password1' %} ui-1_lock-circle-open{% endif %}
{% if field.name == 'password2' %} ui-1_lock-circle-open{% endif %}
"></i>
</span>
{{ field }}
<!-- Give input box red border if data is not valid -->
{% if field.errors %}
<script>
var element = document.getElementById("{{ field.id_for_label }}");
element.classList.add("form-control-danger");
</script>
{% endif %}
</div>
{% endfor %}
<div class="text-center">
Already registered? Log in here
</div>
<!-- If you want to add a checkbox to this form, uncomment this code -->
<!-- <div class="checkbox">
<input id="checkboxSignup" type="checkbox">
<label for="checkboxSignup">
Unchecked
</label>
</div> -->
</div>
<div class="footer text-center">
<button type="submit" class="btn btn-neutral btn-round btn-lg">Get Started</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock page-header %}
And a small example snippet of my index.html of how I want to implement it ish.
index.html
<div class="main">
<div class="section section-about-us">
<div class="container">
<div class="col-md-8 ml-auto mr-auto text-center">
{{ form }}
</div>
</div>
</div>
</div>
I have really tried to find a smooth way of doing this, but without result unfortunately.
It seems as though you already know how to implement the same form in multiple templates, but you've having trouble avoiding repetition in your code. To that end, here are some suggestions for reducing the amount of repetition you'll encounter when duplicating this form across multiple pages:
Validate data within your form rather than your view. Currently, you are checking for duplicate e-mail addresses within views.py. If you duplicated your form, you'd have to re-write that code all over again. Instead, why not move it into forms.py in a custom cleaning method (see Django docs on custom form cleaning).
Write functions for actions that will be repeated. For example, currently, you are sending an activation e-mail to your user within views.py. It makes more sense to write a function within your user/models.py called something like send_activation_email(). Whenever you want to send an activation e-mail to a user, you can then call user.send_activation_email() rather than duplicating your entire block of activation e-mail code (see Django docs on model methods).
Use inclusion tags to avoid repetition in your templates. If there's a block of code that you find yourself repeating in your templates, you can use Django's inclusion tags to include a snippet of HTML across multiple templates. This allows you to serve the same form in multiple locations without re-writing your code. If you want to style your form differently across multiple pages, you could wrap it in DIVs with different IDs and use CSS to style the form differently depending on which DIV it's wrapped in. (see Django docs on inclusion tags)