Bit of a rudimentary Django question. I would like to have a form that asks a user for their name and message and then sends this information to an email (more like a contact form).
This is what I have in my views.py:
def assignmentSubs(request):
if request.method == 'GET':
form = AssignmentSubs()
else:
form = AssignmentSubs(request.POST)
if form.is_valid():
subject = 'Assignment submission: {}'.format(form.cleaned_data['assignment'])
from_email = 'x2x#gmail.com'
message = 'Hi, Please note that {} has submitted an assignment for the {} section. We will reach out to you with more detail regarding this submission'.format(form.cleaned_data['link'],form.cleaned_data['assignment'])
send_mail(subject, message, from_email,['xxx#gmail.com','xxx2.des8#gmail.com'], fail_silently=False)
return render(request, 'form.html', {'form': form})
forms.py
class AssignmentSubs(forms.ModelForm):
assignment = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-field', 'id':'assignmentname'}), required=True)
link = forms.CharField(required=True, max_length=100, widget=forms.TextInput(attrs={'class': 'form-field'}))
and the html with the form
<form method="post" action="/" id="form" class="validate">
{% csrf_token %}
<div class="form-field">
{{form.assignment}}
</div>
<div class="form-field">
{{form.link}}
</div>
<div class="form-field">
<label for=""></label>
<input type="submit" value="Submit Assignment" />
</div>
</form>
and the css:
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#form {
max-width: 700px;
padding: 2rem;
box-sizing: border-box;
}
.form-field {
display: flex;
margin: 0 0 1rem 0;
}
label, input {
width: 70%;
padding: 0.5rem;
box-sizing: border-box;
justify-content: space-between;
font-size: 1.1rem;
}
label {
text-align: right;
width: 30%;
}
input {
border: 2px solid #aaa;
border-radius: 2px;
}
</style>
and my urls.py
This is a two fold problem, I cannot see any of the fields from my form and cannot actually send emails through the form
urlpatterns = [
path('', home, name='home'),
path('about', about, name='about'),
path('courses', courses, name='courses'),
path('notyet', notyet, name='notyet'),
path('faqs',faqs, name='faqs'),
path('students', students, name='students'),
...
Here is the structure of my project
templates
>classroom (folder)
>students
htmlfiles
>teachers
htmlfiles
home.html
>views
students.py (this is the views.py I am referring to)
I've made some changes to your views. Your Form seems fine just make sure the action attribute of your form points to the correct view.
Note: make sure your template i.e form.html is present inside templates directory of your current Django app
from django.shortcuts import render, redirect
def assignmentSubs(request):
if request.method == "GET":
form = AssignmentSubs()
return render(request, "form.html", {"form": form})
else:
form = AssignmentSubs(request.POST)
if form.is_valid():
subject = "Assignment submission: {}".format(
form.cleaned_data["assignment"]
)
from_email = "x2x#gmail.com"
message = "Hi, Please note that {} has submitted an assignment for the {} section. We will reach out to you with more detail regarding this submission".format(
form.cleaned_data["link"], form.cleaned_data["assignment"]
)
send_mail(
subject,
message,
from_email,
["xxx#gmail.com", "xxx2.des8#gmail.com"],
fail_silently=False,
)
# use redirect in any of the following way
# return redirect("some-view-name", foo="bar")
return redirect("/same/valid/url")
Related
I am developing a inventory management and I have to subtract the Quantity from 2 different forms data and display the available quantity.
Below is my views.py
def my_form2(request):
if request.method == "POST":
form2 = MyForm2(request.POST)
if form2.is_valid():
form2.save()
return HttpResponse('Submitted Successfully')
else:
form2 = MyForm2()
return render(request, "authentication/Incoming_QC.html", {'form2': form2})
def View_Incoming_QC(request):
Incoming_QC_list = Incoming_QC.objects.all()
return render(request, 'authentication/View_Incoming_QC.html',
{'Incoming_QC_list': Incoming_QC_list})
def my_form3(request):
if request.method == "POST":
form3 = MyForm3(request.POST)
if form3.is_valid():
form3.save()
return HttpResponse('Submitted successfully')
# return redirect('/home_page/')
else:
form3 = MyForm3()
return render(request, "authentication/Manufacturing.html", {'form3': form3})
def View_Manufacturing(request):
Manufacturing_list = Manufacturing.objects.all()
return render(request, 'authentication/View_Manufacturing.html',
{'Manufacturing_list': Manufacturing_list})
def my_form5(request):
if request.method == "POST":
form5 = MyForm5(request.POST)
if form5.is_valid():
form5.save()
return HttpResponse('Submitted successfully')
# return redirect('/home_page/')
else:
form5 = MyForm5()
return render(request, "authentication/Material.html", {'form5': form5})
def View_Material(request):
Material_list = Material.objects.all()
return render(request, 'authentication/View_Material.html',
{'Material_list': Material_list})
Below is the models.py
class Incoming_QC(models.Model):
alphanumeric = RegexValidator(r'^[\s0-9a-zA-Z\.-_]*$', 'Only alphanumeric characters are allowed.')
Manufacturing_PN = models.CharField(max_length=200, validators=[alphanumeric])
Quantity = models.IntegerField()
class Manufacturing(models.Model):
alphanumeric = RegexValidator(r'^[\s0-9a-zA-Z\.-_]*$', 'Only alphanumeric characters are allowed.')
Manufacturing_PN = models.CharField(max_length=200, validators=[alphanumeric])
Completed_Quantity = models.IntegerField(blank=True, default='')
class Material(models.Model):
alphanumeric = RegexValidator(r'^[\s0-9a-zA-Z\.-_]*$', 'Only alphanumeric characters are allowed.')
Manufacturing_PN = models.CharField(max_length=200, validators=[alphanumeric])
Quantity = models.IntegerField()
.html file to view the data
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
table, th, td {
border:1px solid black;
}
body {
margin-bottom: 100px;
background-color: lightgrey;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #333;
}
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav a.active {
background-color: #04AA6D;
color: white;
}
</style>
</head>
<body>
{% csrf_token %}
{% load static %}
<div class="topnav">
Home
Material Details
View Material Details
</div>
<div style="padding-left:16px">
</div>
<h1>
<center>
Material Details
</center>
</h1>
<table style="width:100%">
<thead>
<tr>
<th>Manufacturing_PN</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
<tr>
{% for Material in Material_list %}
<strong> {{ Material }}</strong>
<td> {{Material.Manufacturing_PN }} </td>
<td> {{Material.Quantity}} </td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
SO here whenever the user submit the incoming QC and Manufacturing forms. The Quantity entered by the user in both the form or single form I want to subtract the Quantity of the Material data.
Note: The Quantity should be subtracted based on the manufacturing_PN.
It should look like below logic:
if Material.manufacturing_PN == Manufacturing.manufacturing_PN || Material.manufacturing_PN == Incoming_QC.manufacturing_PN
Material.manufacturing_PN = Material.manufacturing_PN - Incoming_QC.manufacturing_PN - Manufacturing.manufacturing_PN
It would be very helpful if someone help me out in this. Thanks in advance
I am trying to build a inventory management project facing some difficulty, Looking for a solution.
I have created a 2 form in django model and when I try to load form2 only form1 is loading for all the condition.
I have tried to comment form1 and load only form2 with that I got the expected result but when I try to add run with both the forms I am facing the issue.
Additional to this in django admin panel I am getting I am getting both the forms as expected.
Any kind of help will be appreciated.
Views.py
from .models import Inventory_Details, Incoming_QC
from .forms import MyForm, Incoming_QC_form
def my_form(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse('Submitted successfully')
#return redirect('/home_page/')
else:
form = MyForm()
return render(request, "authentication/Inventory_details.html", {'form': form})
def View_Inventory(request):
Inventory_list = Inventory_Details.objects.all()
return render(request,'authentication/View_Inventory.html',
{'Inventory_list': Inventory_list})
def Incoming_qc_form(request):
if request.method == "POST":
QC_form = Incoming_QC_form(request.POST)
if QC_form.is_valid():
QC_form.save()
return HttpResponse('Submitted successfully')
#return redirect('/home_page/')
else:
QC_form = Incoming_QC_form()
return render(request, "authentication/Incoming_QC.html", {'QC_form': QC_form})
def View_Incoming_QC(request):
Incoming_QC_list = Incoming_QC.objects.all()
return render(request,'authentication/View_Incoming_QC.html',
{'Incoming_QC_list': Incoming_QC_list})
urls.py
url(r'form', views.my_form, name='form'),
path('View_Inventory', views.View_Inventory, name="View_Inventory"),
url(r'QC_form', views.Incoming_qc_form, name='QC_form'),
path('View_Incoming_QC', views.View_Incoming_QC, name="View_Incoming_QC")
html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin-bottom: 100px;
background-color: lightgrey;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #333;
}
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav a.active {
background-color: #04AA6D;
color: white;
}
</style>
</head>
<body>
{% csrf_token %}
{% load static %}
<div class="topnav">
Home
Incoming Quality Check
Inventory Store Management
Inventory Details
Incoming QC details
</div>
<div style="padding-left:16px">
</div>
<div class="container">
<form method="POST">
<fieldset style="margin-block:15px">
<legend>Incoming_QC</legend>
{% csrf_token %}
{{ QC_form.as_p }}
<button type="submit" class="btn btn-primary">Submit</button>
</fieldset>
</form>
</div>
</body>
</html>
forms.py
from django import forms
from .models import Inventory_Details, Incoming_QC
class MyForm(forms.ModelForm):
class Meta:
model = Inventory_Details
fields = ["Invoice_number",
"AWB",
"Received_from",
"Description",
"Quantity",
"Received_date",
"Received_by",
"Assigned_To",
"Manufacturing_PN",]
labels = {'Invoice_number': "Invoice_number",
'AWB':"AWB",
'Received_from':"Received_from",
'Description':"Description",
'Quantity':"Quantity",
'Received_date':"Received_date",
'Received_by':"Received_by",
'Assigned_To':"Assigned_To",
'Manufacturing_PN':"Manufacturing_PN",
'Manufacturer':"Manufacturer",
}
class Incoming_QC_form(forms.ModelForm):
class Meta:
model = Incoming_QC
fields = ["Manufacturer",
"Location",
"Inspected_By",
"Conducted_On",
"Supplier_name",
"Supplier_address",
"PO_number",
"Material_name",
"Part_number",
"Quantity",
]
labels = {'Manufacturer': "Manufacturer",
'Location': "Location",
'Inspected_By': "Inspected_By",
'Conducted_On': "Conducted_On",
'Supplier_name': "Supplier_name",
'Supplier_address': "Supplier_address",
'PO_number': "PO_number",
'Material_name': "Material_name",
'Part_number': "Part_number",
'Quantity': "Quantity",
}
Thanks in advance
Instead of this:
Incoming Quality Check
Inventory Store Management
Try this:
Incoming Quality Check
Inventory Store Management
I think the problem is in view.
Simply try this:
def Incoming_qc_form(request):
if request.method == "POST":
qcform = Incoming_QC_form(request.POST)
if qcform.is_valid():
qcform.save()
return HttpResponse('Submitted successfully')
#return redirect('/home_page/')
else:
qcform = Incoming_QC_form()
return render(request, "authentication/Incoming_QC.html", {'qcform': qcform})
And in template:
{{qcform}}
I need to display weather stations only in the areas(filter by id_ugms) of the country that the user chooses. But the geodjango tools do not allow you to filter the data in the backend. GeoJSONLayerView extracts all the data from the table, and I have to filter the entire list in leaflet on the frontend. There are a lot of records in the table, which is why the response time is very long(it takes more than 5 minutes to display and filter), or it crashes from the server altogether. How do I do backend filtering? Maybe there's another way?
I tried just to make a selection, and serialize the data via geojsonserializer - nothing worked, leaflet does not give an error of input data.
Technology stack: Postgis, Django, Leaflet.
There is a model of my entity:
models.py
class WeatherStation(gismodels.Model):
id_station = models.IntegerField(primary_key=True)
station_index = models.IntegerField(default = None)
name_station_rus = models.CharField(default="", max_length=256)
name_station_en = models.CharField(default="", max_length=256)
id_ugms = models.ForeignKey(Ugms, on_delete=models.CASCADE, default = None)
id_country = models.ForeignKey(Country, on_delete=models.CASCADE, default = None)
id_subrf = models.ForeignKey(Subrf, on_delete=models.CASCADE, default = None)
latitude = models.CharField(default ="", max_length=256)
longitude = models.CharField(default ="", max_length=256)
geom = gismodels.PointField(default ='POINT EMPTY',srid = 4326)
objects = gismodels.Manager()
height_above_sea = models.CharField(default="", max_length=256)
access_level = models.CharField(default="", max_length=256)
def __unicode__(self):
return self.id_station
urls.py
from django.urls import path
from obsnet import views
from django.views.generic import TemplateView
from django.conf.urls import re_path
from djgeojson.views import GeoJSONLayerView
from obsnet.models import WeatherStation
from obsnet.views import StationGeoJSONLayerView
urlpatterns = [
path('', views.home, name='home'),
re_path(r'^filterstation.geojson$', StationGeoJSONLayerView.as_view(), name = 'filterstation'),
]
views.py
from django.contrib.gis.geos import Point, Polygon
from obsnet.models import WeatherStation
from obsnet.forms import FilterForm
from datetime import datetime
from django.shortcuts import render
from django.http import HttpRequest
import json
from django.contrib.gis.geos import GEOSGeometry
from django.core.serializers import serialize
from djgeojson.serializers import Serializer as GeoJSONSerializer
from djgeojson.views import GeoJSONLayerView
from django.conf.urls import re_path
from djgeojson.http import HttpGeoJSONResponse
from django.http import HttpResponseRedirect
from django.urls import reverse
def home(request):
"""Renders the home page."""
assert isinstance(request, HttpRequest)
id_s = None
id_fed = None
id_country = None
id_ugms = None
if request.method == 'POST':
form = FilterForm(request.POST)
# check whether it's valid:
if form.is_valid():
id_ugms = form.cleaned_data.get('filter_ugms')
if (id_ugms == '0') :
id_ugms = None
return render(
request,
'obsnet/index.html',
{
'form' : form,
'title' : 'Home Page',
'year' : datetime.now().year,
'id_ugms' : id_ugms,
},
)
else:
form = FilterForm()
return render(
request,
'obsnet/index.html',
{
'form' : form,
'title' : 'Home Page',
'year' : datetime.now().year,
},
)
class StationGeoJSONLayerView(GeoJSONLayerView):
model = WeatherStation
properties = ['name_station_rus', 'station_index', 'id_subrf', 'id_country', 'id_ugms' ]
def head(self, *args, **kwargs):
response = HttpGeoJSONResponse('')
return response
index.html
{% load leaflet_tags %}
{% load geojson_tags %}
<html>
<head>
{% leaflet_js %}
{% leaflet_css %}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<style>
.filter-map-box{
height: 65%;
width: 20%;
float: left;
position: fixed;
background-color: #ffffff;
top: 5%; /* Расстояние сверху */
left: 5%;
padding: 10px;
-webkit-box-shadow: 5px 5px 15px 5px rgba(0,0,0,0.27);
box-shadow: 5px 5px 15px 5px rgba(0,0,0,0.27);
z-index: 9999;
}
.map-block{
/*width: 75%;*/
}
.leaflet-container { /* all maps */
width: 100%;
height: 100%;
}
#specialbigmap {
height: 1000px;
}
/* Resize the "display_raw" textbox */
.django-leaflet-raw-textarea {
width: 100%;
}
</style>
</head>
<body>
<div class = "map-block">
{% leaflet_map "main" callback="main_map_init" %}
<script type="text/javascript">
function main_map_init (map, options) {
var ugms = '{{ id_ugms }}';
var suburl = '{% url "filterstation" %}';
// Download GeoJSON via Ajax
$.getJSON(suburl, function (filterstation) {
// Add GeoJSON layer
var fea = filterstation.features;
if (ugms !== 'None')
{
for (i = 0; i < fea.length; i++)
{
var prop = fea[i].properties;
if (prop.id_ugms == ugms)
{
console.log(idfiltr );
L.geoJson(filterstation.features[i]).addTo(map).bindPopup(prop.name_station_rus);
}
}
}
});
map.setMaxBounds([[-90,-180], [90,200]]);
map.options.maxBoundsViscosity = 1.0;
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a rel="nofollow" href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
}
</script>
</div>
<div class = "filter-map-box">
<form action="" method="post">
<label for="id_filter_label">Фильтр</label>
{% csrf_token %}
{{ form.as_p }}
<input type="Submit" name="submit" value="Отобразить"/>
</form>
</div>
</body>
</html>
How i would go about it using DRF(django rest framework) and more specifically djangorestframework-gis create a serializer to serializer the data to geojson as follow.
from .models import WeatherStation
from rest_framework_gis.serializers import GeoFeatureModelSerializer
class WeatherStSerializer(GeoFeatureModelSerializer):
class Meta:
model = WeatherStation
geo_field = geom
fields = ('name_station_rus', 'station_index', 'id_subrf', 'id_country', 'id_ugms')
and on views.py do these
from django.http import JsonResponse
from django.views import View
from .serializers import WeatherStSerializer
from .model import WeatherStation
class StationGeoJSONLayerView(View):
def get(self, request):
queryset = WeatherStation.objects.get(id_ugms ="value you need")
geojson = WeatherStSerializer(data=queryset, many=True)
geojson.is_valid()
return JsonResponse(geojson.data, content_type='json', safe=False)
in queryset you can use all the backend filter methods before passing the data to the serializer.
have a look at DRF-gis
im trying to create a django page for update a dta inside database, i made this before in other projects and aways worked, but in my project it returns this error: django.urls.exceptions.NoReverseMatch: Reverse for 'update' with arguments '('',)' not found. 1 pattern(s) tried: ['update/(?P[0-9]+)$']
i reviewed my code a thousand times and i can't see nothing wrong, even if comparing with the other projects.
Obs.: please ignore the css part of my template, i'm not used to write the css inside the html, but as it's just a test i don't create a external file.
urls.py:
from django.urls import path
import tables1.views as vw
urlpatterns = [
path('admin/', admin.site.urls, name = 'admin'),
path('mytables/', vw.mytables, name = 'mytables'),
path('',vw.home),
path('table/<int:pk>',vw.table, name = 'tableurl'),
path('newtable/',vw.newtable,name = 'newtable'),
path('update/<int:pk>',vw.update,name = 'update'),
path('delete/<int:pk>',vw.delete,name = 'delete'),
path('new/',vw.new, name = 'newurl')
]
models.py:
class Table(models.Model):
idd = models.AutoField(primary_key=True, default=None)
name = models.CharField(max_length=100)
date = models.DateField(auto_now_add=True)
time = models.TimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Tables'
def __str__(self):
return self.name
class Transacao(models.Model):
# Forein key defined here
date = models.DateTimeField(auto_now_add=True)
desc = models.CharField(max_length=200)
value = models.DecimalField(max_digits=7, decimal_places=2)
obs = models.TextField(null=True, blank=True)
tableid = models.CharField(max_length=3)
class Meta:
verbose_name_plural = 'Transacoes'
def __str__(self):
return self.desc
views.py:
from .models import Table
from .models import Transacao
from .forms import TableForm
from .forms import TransacaoForm
def home(request):
now = {}
return render(request,'tables1/home.html',now)
def mytables(request):
data = {}
data['tables'] = Table.objects.all()
return render(request, 'tables1/mytables.html', data)
def update(request,pk):
transacao = Transacao.objects.get(pk = pk)
form = TransacaoForm(request.POST or None, instance=transacao)
if form.is_valid():
form.save()
return render(request,'tables1/new.html',{'form':form})
def new(request):
form = TransacaoForm(request.POST or None)
if form.is_valid():
form.save()
return render(request,'contas/form.html',{'form':form})
def delete(request,pk):
transacao = Transacao.objects.get(pk = pk)
transacao.delete()
return redirect('lists')
def table(request,pk):
form = TransacaoForm(request.POST or None)
data = Table.objects.get(idd = pk)
lists = Transacao.objects.filter(tableid = pk)
if request.method == 'POST':
if form.is_valid():
formdesc = form.cleaned_data['desc']
formvalue = form.cleaned_data['value']
transaction_instance = Transacao.objects.create(desc = formdesc,value = formvalue,tableid = pk)
return render(request,'tables1/table.html',{'data':data, 'form':form, 'lists':lists})
def newtable(request):
form = TableForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('mytables')
return render(request,'tables1/newtable.html',{'form':form})
table.html:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {font-family: Arial, Helvetica, sans-serif;}
* {box-sizing: border-box;}
/* Button used to open the contact form - fixed at the bottom of the page */
.open-button {
background-color: #555;
color: white;
padding: 16px 20px;
border: none;
cursor: pointer;
opacity: 0.8;
}
/* The popup form - hidden by default */
.form-popup {
display: none;
bottom: 0;
right-margin: 10px;
right: 15px;
border: 3px solid #f1f1f1;
z-index: 9;
}
/* Add styles to the form container */
.form-container {
max-width: 300px;
padding: 10px;
background-color: white;
}
/* Full-width input fields */
.form-container input[type=text], .form-container input[type=password] {
width: 100%;
padding: 15px;
margin: 5px 0 22px 0;
border: none;
background: #f1f1f1;
}
/* When the inputs get focus, do something */
.form-container input[type=text]:focus, .form-container input[type=password]:focus {
background-color: #ddd;
outline: none;
}
/* Set a style for the submit/login button */
.form-container .btn {
background-color: #4CAF50;
color: white;
padding: 16px 20px;
border: none;
cursor: pointer;
width: 100%;
margin-bottom:10px;
opacity: 0.8;
}
/* Add some hover effects to buttons */
.form-container .btn:hover, .open-button:hover {
opacity: 1;
}
</style>
</head>
<body>
<h1>{{data}}</h1>
<table id = tabela>
<tr>
<th>Item</th>
<th>Data e Hora</th>
<th>Valor</th>
</tr>
{% for list in lists %}
<tr>
<td>{{list.desc}}</td><td>{{list.date}}</td>
<td>{{list.value}}</td><td>{{list.categ}}</td>
<td><form action="{% url 'update' transacao.id %}">
<button type="submit"><b>Editar</b></button>
</form></td>
<td><form action="{% url 'delete' transacao.id %}">
<button type="submit"><b>Excluir</b></button>
</form></td>
</tr>
{%endfor%}
</table>
<button class="open-button" onclick="{% url newurl %}">Nova Transação</button>
<form method="post" class="form-container">
{% csrf_token %}
{{form.as_p}}
<button type="submit" class="btn" onclick="location.reload()">Login</button>
<button type="button" class="btn cancel" onclick="closeForm()">Close</button>
</form>
</body>
</html>
transacao is not a variable in your template, you use list as a variable for a Transacao object, therefore you should use {% url 'update' list.id %} and {% url 'delete' list.id %}:
{% for list in lists %}
<tr>
<td>{{ list.desc }}</td><td>{{ list.date }}</td>
<td>{{ list.value }}</td><td>{{ list.categ }}</td>
<td><form action="{% url 'update' list.id %}">
<button type="submit"><b>Editar</b></button>
</form></td>
<td><form action="{% url 'delete' list.id %}">
<button type="submit"><b>Excluir</b></button>
</form></td>
</tr>
{%endfor%}
That being said, since your lists is not a collection of lists - it is a QuerySet of Transacaos - it might be better to rename lists to transacaos and use transacao as "enumerator".
I am working on an e-commerce project that requires stripe payment gateway. It is my first time to work on an application that requires stripe payment. I am a junior programmer. I am working on my localhost machine, I have tried to debug the code but i have failed to see where the problem is. #Hacker86 got the solution but has not shared it can anyone help me with the problem.
This is the link of the same problem Stack
I tried to solve the problem with the solution in the replies to above the question but all was in veil. So please can anyone help immediately reply me.
Below is my relevant Code
base.py
import os
from decouple import config
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__))))
SECRET_KEY = config('SECRET_KEY')
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_framework',
'drf_yasg',
'crispy_forms',
'django_countries',
'core',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'perfectfits.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'perfectfits.wsgi.application'
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_in_env')]
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media_root')
# Auth
AUTHENTICATION_BACKENDS = (
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by e-mail
'allauth.account.auth_backends.AuthenticationBackend',
)
SITE_ID = 1
LOGIN_REDIRECT_URL = '/'
# CRISPY FORMS
CRISPY_TEMPLATE_PACK = 'bootstrap4'
views.py
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import request
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import ListView, DetailView, View
from django.utils import timezone
from .forms import CheckoutForm, CouponForm, RefundForm
from .models import Item, OrderItem, Order, BillingAddress, Payment, Coupon, Refund
import random
import string
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
def create_ref_code():
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=20))
# Create your views here.
def products(request):
context = {
'items': Item.objects.all()
}
return render(request, "products.html")
class CheckoutView(View):
def get(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
form = CheckoutForm()
context = {
'form': form,
'couponform': CouponForm(),
'order': order,
'DISPLAY_COUPON_FORM': True
}
return render(self.request, "checkout.html", context)
except ObjectDoesNotExist:
messages.info(self.request, "You do not have an active order")
return redirect("core:checkout")
def post(self, *args, **kwargs):
form = CheckoutForm(self.request.POST or None)
try:
order = Order.objects.get(user=self.request.user, ordered=False)
if form.is_valid():
street_address = form.cleaned_data.get('street_address')
apartment_address = form.cleaned_data.get('apartment_address')
country = form.cleaned_data.get('country')
zip = form.cleaned_data.get('zip')
# TODO: add functionality for these fields
# same_shipping_address = form.cleaned_data.get('same_shipping_address')
# save_info = form.cleaned_data.get('save_info')
payment_option = form.cleaned_data.get('payment_option')
billing_address = BillingAddress(
user=self.request.user,
street_address=street_address,
apartment_address=apartment_address,
country=country,
zip=zip
)
billing_address.save()
order.billing_address = billing_address
order.save()
if payment_option == 'S':
return redirect('core:payment', payment_option='stripe')
elif payment_option =='P':
return redirect('core:payment', payment_option='paypal')
elif payment_option =='M':
return redirect('core:payment', payment_option='mobilemoney')
else:
messages.warning(self.request, "Invalid payment option selected")
return redirect('core:checkout')
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect("core:order-summary")
class PaymentView(View):
def get(self, *args, **kwargs):
# order
order = Order.objects.get(user=self.request.user, ordered=False)
if order.billing_address:
context = {
'order': order,
'DISPLAY_COUPON_FORM': False,
'STRIPE_PUBLIC_KEY' : settings.STRIPE_PUBLIC_KEY,
}
return render(self.request, "payment.html", context)
else:
messages.warning(
self.request, "You have not added a billing address")
return redirect("core:checkout")
def post(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
token = self.request.POST.get('stripeToken')
amount = order.get_total()
try:
charge = stripe.Charge.create(
amount=amount, # cents
currency="ugx",
source=token
)
# create the payment
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.user = self.request.user
payment.amount = order.get_total()
payment.save()
# Assign the payment to the order
order_items = order.items.all()
order_items.update(ordered=True)
for item in order_items:
item.save()
order.ordered = True
order.payment = payment
order.ref_code = create_ref_code()
order.save()
messages.success(self.request, "Your order was successful!")
return redirect("/")
except stripe.error.CardError as e:
body = e.json_body
err = body.get('error', {})
messages.warning(self.request, f"{err.get('message')}")
return redirect("/")
except stripe.error.RateLimitError as e:
# Too many requests made to the API too quickly
messages.warning(self.request,"Rate limit error")
return redirect("/")
except stripe.error.InvalidRequestError as e:
# Invalid parameters were supplied to Stripe's API
messages.warning(self.request, "Invalid parameters")
return redirect("/")
except stripe.error.AuthenticationError as e:
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
messages.warning(self.request, "Not authenticated")
return redirect("/")
except stripe.error.APIConnectionError as e:
# Network communication with Stripe failed
messages.warning(self.request, "Network error")
return redirect("/")
except stripe.error.StripeError as e:
# Display a very generic error to the user, and maybe send
# yourself an email
messages.warning(self.request, "Something went wrong. You were not charged. Please try again")
return redirect("/")
except Exception as e:
# Send an email to ourselves
messages.warning(self.request, "A serious error occurred. We have been notified")
return redirect("/")
class HomeView(ListView):
model = Item
paginate_by = 10
template_name = "home.html"
class OrderSummaryView(LoginRequiredMixin, View):
def get(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
context = {
'object': order
}
return render(self.request, 'order_summary.html', context)
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect("/")
class ItemDetailView(DetailView):
model = Item
template_name = "product.html"
#login_required
def add_to_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_item, created = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)
order_qs = Order.objects.filter(user=request.user, ordered=False) # qs is query set
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item.quantity += 1
order_item.save()
messages.info(request, "This item quantity was updated.")
return redirect("core:order-summary")
else:
order.items.add(order_item)
messages.info(request, "This item was added to your Cart.")
return redirect("core:order-summary")
else:
ordered_date = timezone.now()
order = Order.objects.create(
user=request.user, ordered_date=ordered_date)
order.items.add(order_item)
messages.info(request, "This item was added to your Cart.")
return redirect("core:order-summary")
#login_required
def remove_from_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_qs = Order.objects.filter(
user=request.user,
ordered=False
)
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)[0]
order.items.remove(order_item)
messages.info(request, "This item was removed from your Cart.")
return redirect("core:order-summary")
else:
messages.info(request, "This item was not in your cart.")
return redirect("core:product", slug=slug)
else:
messages.info(request, "You do not have an active order.")
return redirect("core:product", slug=slug)
#login_required
def remove_single_item_from_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_qs = Order.objects.filter(
user=request.user,
ordered=False
)
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)[0]
if order_item.quantity > 1:
order_item.quantity -= 1
order_item.save()
else:
order.items.remove(order_item)
messages.info(request, "This item quantity was updated.")
return redirect("core:order-summary")
else:
messages.info(request, "This item was not in your cart.")
return redirect("core:product", slug=slug)
else:
messages.info(request, "You do not have an active order.")
return redirect("core:product", slug=slug)
def get_coupon(request, code):
try:
coupon = Coupon.objects.get(code=code)
return coupon
except ObjectDoesNotExist:
messages.info(request, "This Coupon does not exist")
return redirect("core:checkout")
class AddCouponView(View):
def post(self, *args, **kwargs):
form = CouponForm(self.request.POST or None)
if form.is_valid():
try:
code = form.cleaned_data.get('code')
order = Order.objects.get(
user=self.request.user, ordered=False)
order.coupon = get_coupon(self.request, code)
order.save()
messages.success(self.request, "Successfully added coupon")
return redirect("core:checkout")
except ObjectDoesNotExist:
messages.info(self.request, "You do not have an active order")
return redirect("core:checkout")
class RequestRefundView(View):
def get(self, *args, **kwargs):
form = RefundForm()
context = {
'form': form
}
return render(self.request, "request_refund.html", context)
def post(self, *args, **kwargs):
form = RefundForm(self.request.POST)
if form.is_valid():
ref_code = form.cleaned_data.get('ref_code')
message = form.cleaned_data.get('message')
email = form.cleaned_data.get('email')
# edit the order
try:
order = Order.objects.get(ref_code=ref_code)
order.refund_requested = True
order.save()
# store the refund
refund = Refund()
refund.order = order
refund.reason = message
refund.email = email
refund.save()
messages.info(self.request, "Your request was received.")
return redirect("core:request-refund")
except ObjectDoesNotExist:
messages.info(self.request, "This order does not exist.")
return redirect("core:request-refund")
payment.html
{% extends "base.html" %}
{% block extra_head %}
<style>
#stripeBtnLabel {
font-family: "Helvetica Neue", Helvetica, sans-serif;
font-size: 16px;
font-variant: normal;
padding: 0;
margin: 0;
-webkit-font-smoothing: antialiased;
font-weight: 500;
display: block;
}
#stripeBtn {
border: none;
border-radius: 4px;
outline: none;
text-decoration: none;
color: #fff;
background: #32325d;
white-space: nowrap;
display: inline-block;
height: 40px;
line-height: 40px;
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
border-radius: 4px;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.025em;
text-decoration: none;
-webkit-transition: all 150ms ease;
transition: all 150ms ease;
float: left;
width: 100%
}
button:hover {
transform: translateY(-1px);
box-shadow: 0 7px 14px rgba(50, 50, 93, .10), 0 3px 6px rgba(0, 0, 0, .08);
background-color: #43458b;
}
.stripe-form {
padding: 5px 30px;
}
#card-errors {
height: 20px;
padding: 4px 0;
color: #fa755a;
}
.stripe-form-row {
width: 100%;
float: left;
margin-top: 5px;
margin-bottom: 5px;
}
/**
* The CSS shown here will not be introduced in the Quickstart guide, but shows
* how you can use CSS to style your Element's container.
*/
.StripeElement {
box-sizing: border-box;
height: 40px;
padding: 10px 12px;
border: 1px solid transparent;
border-radius: 4px;
background-color: white;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
.current-card-form {
display: none;
}
</style>
{% endblock extra_head %}
{% block content %}
<main >
<div class="container wow fadeIn">
<h2 class="my-5 h2 text-center">Payment</h2>
<div class="row">
<div class="col-md-12 mb-4">
<div class="card">
{% if card %}
<div style="padding: 5px 30px;">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" name="use_default_card" id="use_default_card">
<label class="custom-control-label" for="use_default_card">Use default card:
**** **** **** {{ card.last4 }}
<span>Exp: {{ card.exp_month }}/{{ card.exp_year }}</span></label>
</div>
</div>
{% endif %}
<div class="current-card-form">
<form action="." method="post" class="stripe-form">
{% csrf_token %}
<input type="hidden" name="use_default" value="true">
<div class="stripe-form-row">
<button id="stripeBtn">Submit Payment</button>
</div>
<div id="card-errors" role="alert"></div>
</form>
</div>
<div class="new-card-form">
<form action="." method="post" class="stripe-form" id="stripe-form">
{% csrf_token %}
<div class="stripe-form-row" id="creditCard">
<label for="card-element" id="stripeBtnLabel">
Credit or debit card
</label>
<div id="card-element" class="StripeElement StripeElement--empty"><div class="__PrivateStripeElement" style="margin: 0px !important; padding: 0px !important; border: none !important; display: block !important; background: transparent !important; position: relative !important; opacity: 1 !important;"><iframe frameborder="0" allowtransparency="true" scrolling="no" name="__privateStripeFrame5" allowpaymentrequest="true" src="https://js.stripe.com/v3/elements-inner-card-19066928f2ed1ba3ffada645e45f5b50.html#style[base][color]=%2332325d&style[base][fontFamily]=%22Helvetica+Neue%22%2C+Helvetica%2C+sans-serif&style[base][fontSmoothing]=antialiased&style[base][fontSize]=16px&style[base][::placeholder][color]=%23aab7c4&style[invalid][color]=%23fa755a&style[invalid][iconColor]=%23fa755a&componentName=card&wait=false&rtl=false&keyMode=test&origin=https%3A%2F%2Fstripe.com&referrer=https%3A%2F%2Fstripe.com%2Fdocs%2Fstripe-js&controllerId=__privateStripeController1" title="Secure payment input frame" style="border: none !important; margin: 0px !important; padding: 0px !important; width: 1px !important; min-width: 100% !important; overflow: hidden !important; display: block !important; height: 19.2px;"></iframe><input class="__PrivateStripeElement-input" aria-hidden="true" aria-label=" " autocomplete="false" maxlength="1" style="border: none !important; display: block !important; position: absolute !important; height: 1px !important; top: 0px !important; left: 0px !important; padding: 0px !important; margin: 0px !important; width: 100% !important; opacity: 0 !important; background: transparent !important; pointer-events: none !important; font-size: 16px !important;"></div></div>
</div>
<div class="stripe-form-row">
<button id="stripeBtn">Submit Payment</button>
</div>
<div class="stripe-form-row">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" name="save" id="save_card_info">
<label class="custom-control-label" for="save_card_info">Save for future purchases</label>
</div>
</div>
<div id="card-errors" role="alert"></div>
</form>
</div>
</div>
</div>
{% include "order_snippet.html" %}
</div>
</div>
</main>
{% endblock content %}
{% block extra_scripts %}
<script src="https://js.stripe.com/v3/"></script>
<script nonce=""> // Create a Stripe client.
var stripe = Stripe('{{STRIPE_PUBLIC_KEY}}');
// Create an instance of Elements.
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
var form = document.getElementById('stripe-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
// Submit the form with the token ID.
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('stripe-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
var currentCardForm = $('.current-card-form');
var newCardForm = $('.new-card-form');
var use_default_card = document.querySelector("input[name=use_default_card]");
use_default_card.addEventListener('change', function() {
if (this.checked) {
newCardForm.hide();
currentCardForm.show()
} else {
newCardForm.show();
currentCardForm.hide()
}
})
</script>
{% endblock extra_scripts %}