How use TemplateView with 2 methods (get and post) - django

I am trying to use Templateview in Django to render a page with options for both adding to the database and retrieving some info from the database and displaying it. I am basing it on the tutorial at https://www.youtube.com/watch?v=VxOsCKMStuw
views.py:
class TestView(TemplateView):
template_name = 'app/sensor_name_tmpl.html'
def get(self, request):
form = SensorForm()
posts = Sensor.objects.all()
args = {'form': form, 'posts': posts}
return render(request, self.template_name, args)
def post(self, request):
form = SensorForm(request.POST)
if form.is_valid():
form.save()
text = form.cleaned_data['post']
form = SensorForm()
return redirect('sensor_name_tmpl:sensor_name_tmpl')
args = {'form': form, 'text': text}
return render(request, self.template_name, args)
urls.py:
urlpatterns = [
path('', views.index, name='index'),
url(r'^form1/$', views.get_sensor_name, name='GiveSensorName1'),
#url(r'^form2/$', TestView.as_view(), name='sensor_name_tmpl.html'),
path('form2/', TestView.as_view(), name='app/sensor_name_tmpl.html'),
url(r'^nested_admin/', include('nested_admin.urls')),
]
HTML template:
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script>
$('#toggle').click(function() {
$('form').toggle('slow');
});
</script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<title>Hello world!</title>
</head>
<body>
<h3 class="text-success">Add Sensor</h3>
<br>
<!-- <form style="display:none;" method="post">-->
<form method="post">
{% csrf_token %}
<div class="row align-items-center">
<div class="col-sm-8">
<table>
{{ form1.as_table}}
</table>
<div class="mx-sm-2">
<input type="submit" value="Submit">
</div>
<br>
<br>
<h3 class = "text-success">Add Sensor View</h3>
<table>
{{ form2.as_table}}
</table>
<div class="mx-sm-2">
<input type="submit" value="Submit">
</div>
<br>
<br>
<h3 class="text-success">View Sensors</h3>
<table class="table">
<thead>
<tr>
<th scope="col">Sensor ID</th>
<th scope="col">Sensor Name</th>
</tr>
</thead>
<tbody>
{%for obj in obj%}
<tr>
<td>{{obj.sensor_id}}</td>
<td>{{obj.sensor_name}}</td>
<!-- <th scope="row">1</th>-->
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div>
</form>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
</body>
</html>
The page renders the template but doesn't populate it with either the formfields or the data from the database.

The problem was with the HTML template where form1 and form2 have now been replaced with form and "obj" in the for loop has been replaced with "posts". The template now looks as follows:
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script>
$('#toggle').click(function() {
$('form').toggle('slow');
});
</script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<title>Hello world!</title>
</head>
<body>
<h3 class="text-success">Add Sensor</h3>
<br>
<!-- <form style="display:none;" method="post">-->
<form method="post">
{% csrf_token %}
<div class="row align-items-center">
<div class="col-sm-8">
<table>
{{ form.as_table}}
</table>
<div class="mx-sm-2">
<input type="submit" value="Submit">
</div>
<br>
<br>
<h3 class = "text-success">Add Sensor View</h3>
<table>
{{ form.as_table}}
</table>
<div class="mx-sm-2">
<input type="submit" value="Submit">
</div>
<br>
<br>
<h3 class="text-success">View Sensors</h3>
<table class="table">
<thead>
<tr>
<th scope="col">Sensor ID</th>
<th scope="col">Sensor Name</th>
</tr>
</thead>
<tbody>
{%for obj in posts%}
<tr>
<td>{{obj.sensor_id}}</td>
<td>{{obj.sensor_name}}</td>
<!-- <th scope="row">1</th>-->
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div>
</form>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
</body>
</html>

Being a beginner Django Developer, I will suggest that it is actually not advisable to use TemplateView class for any kind updating of objects or if your template is having a form. You can read more about this here.

Related

Why django template not render tag after include tag

i consider that why template not render tag after {% include %}. when i put some tag like something in front of include tag, it work. But it not work if i try to put behind the include tag. :(
in index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<link rel="stylesheet" href="{% static 'styles/main.css' %}" />
<script
src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous">
</script>
</head>
<body>
<div class="d-flex">
{% include 'navbar.html' %}
<div class="content">
<div class="header">
{% include 'header.html' %}
</div>
<div>
{% block subHeader %}
{% endblock %}
</div>
<div>
{% block list %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>
in list.html
<table class="table">
<thead>
<tr>
<th scope="col">Cardinal Number</th>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Category</th>
<th scope="col">Cost</th>
<th scope="col">Note</th>
<th scope="col">Image</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>#twitter</td>
</tr>
</tbody>
</table>
in products.html
{% extends 'index.html' %}
{% block subHeader %}
{% include 'components/subHeader.html' with url="api/add-product" name="product"
selectName="product-category" %}
{% endblock subHeader%}
{% block list %}
{% include 'components/list.html' %}
{% endblock content%}
although i put whatever after include tag in block subHeader, it not work. i dont understand why that. Can someone point me ? Thanks

How do I search 2 tables in

I am continuing to learn Django as a newbie.....I would like some direction in relation to 1 search query against two tables that hold the same headers such as customer names.
So table 1 is customer names from 2022 and table 2 is customer names from 2021.
I can create the models / admin and URL and set the project up.
How do I create a query to search both tables at the same time and display the result?
View.py
def index(request,):
q = request.GET.get('q')
if q:
#this is what is searched against.....ie the columns in our model.py
vector = SearchVector('name')
#This is the value the user is searching for:
query = SearchQuery (q)
# customers = customer.objects.filter(name__search=q)
# customers = customer.objects.annotate(search=vector).filter(search=query)
customers = customer1.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.001).order_by('-rank')
else:
customers = None
context = {'customers': customers}
return render(request, 'index.html', context)
Index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GAEN</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>
{% include 'navbar.html' %}
<div class="container">
{% block content %}
<br><br><br><br>
<form>
<div class="mb-3">
<label for="Search Query" class="form-label ">
<h3>db Search Query</h3>
</label>
<br><br>
<input type="text" class="form-control" aria-describedby="#" name="q">
<br><br>
<button type="submit" class="btn btn-primary ">Submit</button>
<button type="submit" class="btn btn-danger">Reset</button>
</div>
</form>
{% if customers %}
<br>
<h3><mark>Results:</mark> {{ customer | length }}</h3>
<br><br>
{% for customer in customers %}
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Search Result</th>
<th scope="col">name</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>{{ customer.name }}</td>
</tr>
</tbody>
</table>
Rank: {{ customer.rank }}
<br><br><br>
{% endfor %}
{% endif %}
{% endblock %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2"
crossorigin="anonymous"></script>
Django-filter can do it easily!

CRUD IN THE SAME PAGE DJANGO

I am trying to do a CRUD using only one html page with django, but I have already encountered the first problem, when using nav-tabs I am not able to load the form when I click on the Create / Edit tab, maybe it has something to do with urls, but I don't know.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>Ordens de Serviço</h2>
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#list">Ordens de Serviço</a></li>
<li><a data-toggle="tab" href="#create-update">Criar/Editar</a></li>
<li><a data-toggle="tab" href="#detail">Ver</a></li>
</ul>
<div class="tab-content">
<div id="list" class="tab-pane fade in active">
<h3>Ordens de Serviço</h3>
<table class="table">
<thead>
<tr>
<th>Nome</th>
<th>TAG</th>
<th>nivel</th>
</tr>
</thead>
<tbody>
{%for equipamento in equipamentos %}
<tr>
<td>{{equipamento.nome}}</td>
<td>{{equipamento.tag}}</td>
<td>{{equipamento.nivel}}</td>
<td><a><button class="btn btn-primary">Editar</button></a></td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
<div id="create-update" class="tab-pane fade">
<h3>Criar/Editar</h3>
<form method="post">
{% csrf_token %}
{{form}}
</form>
</div>
<div id="detail" class="tab-pane fade">
<h3>Menu 2</h3>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.</p>
</div>
</div>
</div>
<script>
</script>
</body>
</html>
views.py:
class ArvoreListView(ListView):
queryset = Arvore.objects.all()
template_name = 'example/index.html'
context_object_name = 'equipamentos'
class ArvoreCreateView(CreateView):
form_class = ArvoreModelForm
model = Arvore
template_name = 'example/create.html'
urls.py
urlpatterns = [
path('', ArvoreListView.as_view(), name='list'),
path('create/', ArvoreCreateView.as_view(), name='create'),
]
when I click on the second tab the form does not render

Display error message on PasswordChangeForm

I am PasswordChangeForm form to change password. I am trying to display an error message when given password is either less than 8 or greater than 64 (in below code "form.data['new_password1']"). So when I enter password with less than 8 characters, then I am seeing error message "New password should have minimum 8 characters and maximum 64 characters" hit. But error message not displayed on UI page. This is because "return render(request, 'registration/change_password.html'" renders again.
Could you please help me how can we display error message on PasswordChangeForm.
#login_required(login_url='/login/')
def change_password_view(request):
global passwordValidationFailed
passwordValidationFailed = False
if (request.method == 'POST'):
form = PasswordChangeForm(request.user, request.POST)
if len(form.data['new_password1']) >= 8 and len(form.data['new_password1']) <= 64:
if form.is_valid():
form.save()
messages.success(request, 'Your password was successfully updated!')
profile = request.user.get_profile()
profile.force_password_change = False
profile.save()
return render(request, 'dau_gui_app/status_view.html', {'title': "System Status"})
else:
passwordValidationFailed = False
messages.error(request, 'Please correct the error below.')
else:
raise form.ValidationError("New password should have minimum 8 characters and maximum 64 characters")
else:
form = PasswordChangeForm(request.user)
return render(request, 'registration/change_password.html', {
'form': form
})
Here is my change_password.html
{% load i18n %}
{% load admin_static %}{% load firstof from future %}<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="static/dau_gui_app/fontawesome-free-5.3.1-web/css/all.min.css">
<link rel='shortcut icon' type='image/x-icon' href='/static/dau_gui_app/images/favicon.ico' />
<link rel="stylesheet" href="/static/dau_gui_app/style.css">
<link rel="stylesheet" href="/static/dau_gui_app/bootstrap.min.css">
<link rel="stylesheet" href="/static/dau_gui_app/w3.css">
<link rel="stylesheet" href="/static/dau_gui_app/dataTables/datatables.css">
<script type="text/javascript" src="/static/dau_gui_app/dataTables/jQuery-3.3.1/jquery-3.3.1.js"></script>
<script type="text/javascript" src="/static/dau_gui_app/dataTables/datatables.js"></script>
<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% static 'admin/css/base.css' %}{% endblock %}" />
{% block extrastyle %}{% endblock %}
<title>
{% block title %}Change Password{% endblock %}
</title>
</head>
{% load i18n %}
<body id="login_page">
<DIV style="margin-left:auto;margin-right:auto;padding-top:100px;display:block;width:30%">
<DIV id="login_box">
<table id="logon_box_table" >
<!-- Title Bar -->
<TR >
<TD colspan='2' >
<DIV id='login_box_title'>
Update Password
</DIV>
</TD>
</TR>
<!-- Password -->
<TR >
<TD >
<div id= "logon-container" >
<img src="/static/dau_gui_app/images/logo.png" alt="">
<div id="alstom-logo-container"> <img src="/static/dau_gui_app/images/alstom_logo.png" alt="" style="width: 90px; height: 18px;"> </div>
<div id="version-container" >Software Version: 4.0</div>
</div>
</TD>
<TD style="width: 490px; height: 18px;">
{% block content %}
<form method="post">
{% csrf_token %}
{{ form }}
</TD>
</TR>
<TR >
<TR >
<TD colspan='2' style="text-align:center;padding:10px">
<button type="submit">Update Password</button>
</form>
{% endblock %}
</TD>
</TR>
</TABLE>
</DIV>
</DIV>
</body>
</html>
You are taking the wrong approach. You should validate the input in the Form, not in the View. That's because any error you raise in the form's full_clean() process will be caught and added to the form errors, which you display in your template.
In your view, when you do raise ValidationError(...), this actually produces an exception to be raised and hence, you return an HTTP 500 error.
Since you only need to clean one particular field, override the specific field's clean method inside the form as explained here:
def clean_new_password1(self):
data = self.cleaned_data['new_password1']
if len(data) < 8 or len(data) > 64:
raise form.ValidationError("New password should have minimum 8 characters and maximum 64 characters")
return data

Form not displaying on Django site

I have just started learning Django and I have hit a little snag and was hoping someone could help.
Problem:
My form is not displaying in my main HTML template (ingredior.html) but the form will display in my test HTML template (test.html) which is just a boiler plate HTML file with the {{form1}} tag in the body. I am changing "return render(request, 'ingredior/ingredior.html', context)" in the views.py file manually to test the two different HTML templates.
ingredior.html
test.html
Question:
Why is the form working in the test.html and not the ingredior.html file when changed?
Please keep in mind that I am swapping this line of code "return render(request, 'ingredior/ingredior.html', context)" with "return render(request, 'ingredior/test.html', context)" to test between the two.
CODE---------
Forms.py
from django import forms
class UserInput(forms.Form):
base_search_ingredient = forms.ChoiceField(choices=[('vegan', 'Vegan'), ('vegatarian', 'Vegatarian')])
views.py
from django.shortcuts import render
import requests
from .local_api_key import Key
from .forms import UserInput
def index (request):
app_id = Key.app_id
app_key = Key.app_key
search_from = 0
search_to = 100
form1 = UserInput()
test = []
if request.POST.get('search'):
test2 = request.POST.get('search')
intolerance = test2
url = requests.get(f"https://api.edamam.com/search?q={intolerance}&excluded=egg&excluded=beef&excluded=dairy&excluded=tomato&excluded=cherry%20tomatoes&excluded=rice&excluded=corn&excluded=soy&excluded=onion&from={search_from}&to={search_to}&health={intolerance}&app_id={app_id}&app_key={app_key}").json()
recipe_length = (len(url['hits']))
else:
intolerance = 'vegan'
url = requests.get(f"https://api.edamam.com/search?q={intolerance}&excluded=egg&excluded=beef&excluded=dairy&excluded=tomato&excluded=cherry%20tomatoes&excluded=rice&excluded=corn&excluded=soy&excluded=onion&from={search_from}&to={search_to}&health={intolerance}&app_id={app_id}&app_key={app_key}").json()
recipe_length = (len(url['hits']))
for urls in range(recipe_length):
recipe_name = (url['hits'][urls]['recipe']['label'])
recipe_url = (url['hits'][urls]['recipe']['url'])
recipe_image = (url['hits'][urls]['recipe']['image'])
recipe_healthLabels = (url['hits'][urls]['recipe']['healthLabels'])
recipe_ingredients = (url['hits'][urls]['recipe']['ingredientLines'])
test.append((recipe_name, recipe_url, recipe_image, recipe_healthLabels, recipe_ingredients))
context = {'test': test, 'form1': form1}
return render(request, 'ingredior/ingredior.html', context)
ingredior.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Nake Recipes</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href=>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
.card {
width: 300px;
height: 700px;
overflow: scroll;
float: left;
margin: 13px;
}
.list {
line-height: 2em;
text-align: left;
}
.card-content ul {
height: 100px
overflow-y: scroll;
}
.container h1 {
text-align: center;
}
</style>
</head>
<body>
<nav>
<div class="container nav-wrapper">
Naked Recipes
<ul id="nav-mobile" class="right">
<li>Home</li>
</ul>
</div>
</nav>
<div class="container">
<h1 style="text-align: c">What intolerance do you have?</h1>
<div class="row">
<div class="col s4">
<!-- Promo Content 1 goes here -->
<div class="center">
<i class="large material-icons" style="color: #EE6E73">flash_on</i>
<p></p>
<p class="light center"></p>
</div>
</div>
<div class="col s4">
<!-- Promo Content 2 goes here -->
<div class="center">
<i class="large material-icons" style="color: orange">camera</i>
<p></p>
<p class="light center"></p>
</div>
</div>
<div class="col s4">
<!-- Promo Content 3 goes here -->
<div class="center">
<i class="large material-icons" style="color: blue">chrome_reader_mode</i>
<p></p>
<p class="light center"></p>
</div>
</div>
</div>
<br>
<form action="" method="post">
{% csrf_token %}
{{ form1 }}
</form>
<br>
<div class="row">
{% for item in test %}
<div class="col_s2">
<div class="card">
<div class="card-image">
<img src= {{ item.2 }} alt="">
</div>
<div class="card-content scroll">
{{ item.0 }}<br><br>
<p>
<b>Ingredients</b><br>
</p>
<ul class="list">
{% for litem in item.4 %}
<li>- {{ litem }}</li>
{% endfor %}
</ul>
<ul class="list">
<p>
<b>Allergies</b>
</p>
{% for litem in item.3 %}
<li>- {{ litem }}</li>
{% endfor %}
</ul>
</div>
<div class="card-action">
<a href={{ item.1 }}>Get Full Recipe </a>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</body>
</html>
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post" >
{% csrf_token %}
{{ form1 }}
</form>
</body>
</html>
app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name="index"),
]
Thank you in advance 😅
** UPDATE **
On further investigation :
Inspection Image ingredior.html
Inspection Image test.html
They are the same.