How to send data from CBV form to a template CBV? - python

I'm trying to send the POST data from a CBV form to other CBV.
I use the valid_form method to get the info by form.cleaned_data and then i apply in this method some custom methods.
But I cant send the result to the other view.
Also I tried put an action in the html sending to the other template and then grab the data but I cant.
views.py
from django.shortcuts import render
from django.views.generic.edit import FormView
from django.views.generic.base import TemplateView
from .forms import QuoteForm
from .models import SmgQuotesTable
from .quotes import Quotes
class QuoteFormView(FormView):
template_name = 'core/home.html'
form_class = QuoteForm
success_url = 'quotes'
def form_valid(self, form):
name = form.cleaned_data['name']
email = form.cleaned_data['email']
couple = form.cleaned_data['couple']
age = form.cleaned_data['age']
kids = form.cleaned_data['kids']
#query_filter = Quotes().planSelector(couple, kids, age)
#obj = SmgQuotesTable.objects.filter(composite='Ind. Junior (H25)')
return super(QuoteFormView, self).form_valid(form)
class QuoteListView(ListView):
model = SmgQuotesTable
def get_queryset(self):
queryset = super(QuoteListView, self).get_queryset()
queryset = queryset #
print(queryset)
return queryset
home.html
{% block content %}
<style>label{display:none}</style>
<form method="post" action="{% url 'quotes-list' %}">{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-primary btn-block py-2" value="Cotizar">
</form>
{% endblock %}
urls.py
from django.urls import path
from .views import QuoteFormView, QuoteListView
urlpatterns = [
path('', QuoteFormView.as_view(), name='home'),
path('quotes/', QuoteListView.as_view(), name='quotes-list'),
]
I expect to grab the name, email, couple, age and kids values in the QuoteView and apply the Quotes method so i can print the result in the quotes.html

I solve it.
In views.py replace the form_Valid method in the form view with the get_query method in the ListView.
With the self.request.GET() I get the info and pase it to the custom quot method.
Then i return the filtered information with the result.
from django.shortcuts import render
from django.views.generic.edit import FormView
from django.views.generic.list import ListView
from .forms import QuoteForm
from .models import SmgQuotesTable
from .quotes import Quotes
class QuoteFormView(FormView):
template_name = 'core/home.html'
form_class = QuoteForm
success_url = 'quotes'
class QuoteListView(ListView):
model = SmgQuotesTable
def get_queryset(self):
r_get = self.request.GET
d_get = {'name': None , 'email':None , 'couple': None, 'age': None, 'kids':None ,}
for value in d_get:
d_get[value] = r_get[value]
query_filter = Quotes().planSelector(d_get['couple'], d_get['kids'], d_get['age'])
queryset = super(QuoteListView, self).get_queryset().filter(composite=query_filter)
return queryset
In home.html have to change the POST method to a GET method, because the list view dont allow POST.
Adding in the the action to the ListView template I send the data in the form to takeit with the self.request.GET in the get_queryset() method.
{% extends 'core/base.html' %}
{% block title %}Cotizador{% endblock %}
{% load static %}
{% block headers %}
<h1>Cotizador</h1>
<span class="subheading">Cotiza tu plan!</span>
{% endblock %}
{% block content %}
<style>label{display:none}</style>
<form method="get" action="{% url 'quotes-list' %}">{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-primary btn-block py-2" value="Cotizar">
</form>
{% endblock %}
Finaly i put the information in the smgquotestable_list using the object_list and the properties of the model.
{% extends 'core/base.html' %}
{% block title %}Cotización{% endblock %}
{% load static %}
{% block headers %}
<h1>Cotización</h1>
<span class="subheading">Cotización</span>
{% endblock %}
{% block content %}
{% for item in object_list %}
<div class="table-responsive text-nowrap"></div>
<table class="table table-striped">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">SMG01</th>
<th scope="col">SMG02</th>
<th scope="col">SMG10</th>
<th scope="col">SMG20</th>
<th scope="col">SMG30</th>
<th scope="col">SMG40</th>
<th scope="col">SMG50</th>
<th scope="col">SMG60</th>
<th scope="col">SMG70</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">{{ item.composite }}</th>
<td>$ {{ item.smg01 }}</td>
<td>$ {{ item.smg02 }}</td>
<td>$ {{ item.smg10 }}</td>
<td>$ {{ item.smg20 }}</td>
<td>$ {{ item.smg30 }}</td>
<td>$ {{ item.smg40 }}</td>
<td>$ {{ item.smg50 }}</td>
<td>$ {{ item.smg60 }}</td>
<td>$ {{ item.smg70 }}</td>
</tr>
</tbody>
</table>
</div>
{% endfor %}
{% endblock %}

Related

Why this DeleteView doesn't actually delete the entry in Django?

In my Django app the delete view doesn't work. When I click on an entry the page just refreshes and nothing happens. The entry is not deleted from the database. Creating and updating entries works fine. Is there something wrong with any of the files?
microtarjetas/views.py:
class DeleteCardView(DeleteView):
model = Card
template_name = 'microtarjetas/delete_card.html'
form_class = CardForm
success_url = '/cards/'
templates/microtarjetas/delete_card.html:
{% extends 'base.html' %} {% load static %} {% block content %}
<h2>Delete card</h2>
<p>Are you sure you want to delete "{{ object }}"?</p>
<form method="post">{% csrf_token %}
<input type="submit" value="Confirm" />
</form>
{% endblock %}
a snippet from templates/microtarjetas/cards.html:
<tbody>
{% for card in cards %}
<tr>
<td>{{ card.word_en }}</td>
<td>{{ card.word_es }}</td>
<td>update</td>
<td>X</td>
</tr>
{% endfor %}
</tbody>
forms.py:
from django import forms
from .models import Card
class CardForm(forms.ModelForm):
class Meta:
model = Card
fields = "__all__"
models.py:
class Card(models.Model):
word_en = models.CharField(max_length = 30)
word_es = models.CharField(max_length = 30)
def get_absolute_url(self):
return "/cards"
def __str__(self):
return f"{self.word_en} --- {self.word_es}"
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.HomeView.as_view(), name='home'),
path('cards/', views.CardsView.as_view(), name='cards'),
path('cards/new', views.CreateCardView.as_view(), name='create_card'),
path('cards/<pk>/delete/', views.DeleteCardView.as_view(), name='delete_card'),
path('cards/<pk>/update/', views.UpdateCardView.as_view(), name='update_card'),
]
I add a {{ form }} tag to the delete_card.html form, it works (although it adds two input fields to the form which are unnecessary):
delete_card.html
You are not submitting the form with the form data. You should update the code like this:
<form method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Confirm" />
</form>
More information can be found in the documentation.

I want to add create bar with add button in Django

I am new to django and kind of confuse why it's not working
I making list website where you add something on list and it updates shows the new added element on the same page. I am almost done the only thing left is creating new element where i am facing problem. Thank you
models.py:-
from django.db import models
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse
# Create your models here.
class simpleList(models.Model):
title = models.CharField(max_length=250)
def __str__(self):
return self.title
views.py:-
from django.shortcuts import render, get_object_or_404
from .models import simpleList
from django.views.generic import ListView, DeleteView, CreateView
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
# Create your views here.
class ListListView(ListView):
model = simpleList
template_name = 'list_list.html'
class DeleteList(SuccessMessageMixin, DeleteView):
model = simpleList
success_url = reverse_lazy('list_list')
success_message = "deleted..."
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
title = self.object.title
request.session['title'] = title
return super(DeleteView, self).delete(request, *args, **kwargs)
class CreateList(CreateView):
model = simpleList
template_name = 'list_list.html'
urls.py:-
from django.urls import path
from .views import ListListView, DeleteList, CreateList
from django.conf.urls import url
from . import views
urlpatterns = [
path('', ListListView.as_view(), name='list_list'),
path('<int:pk>/delete/', DeleteList.as_view(), name='delete_view'),
path('new/', CreateList.as_view(), name='create_list'),
]
list_list.html:-
{% extends 'base.html' %}
{% block title %}sList{% endblock title %}
{% block content %}
<h2>simpleList</h2>
<form action="{% url 'create_list' pk=simpleList.pk %}" method=" POST">{% csrf_token %}
{{ form.as_p }}
<button type="submit">Add</button>
</form>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">S.No</th>
<th scope="col">Task</th>
<th scope="col">Done</th>
</tr>
</thead>
</table>
<div>
{% for simpleList in object_list %}
<table class="table table-hover">
<thead style="display: none;">
<tr>
<th scope="col">S.No</th>
<th scope="col">Task</th>
<th scope="col">Done</th>
</tr>
</thead>
<div>
<tbody>
<tr class="table-primary">
<th scope="row">{{ simpleList.pk }}</th>
<td style="max-width: 100px; word-break: break-all;">
{{ simpleList.title }}
</td>
<td>
<form method="POST" action="{% url 'delete_view' pk=simpleList.pk %}">{% csrf_token %}
<input class="btn btn-default btn-danger" type="submit" value="Done" />
</form>
</td>
</tr>
</tbody>
</div>
</table>
</div>
{% endfor %}
{% endblock content %}
The error i am receiving is this:-
Reverse for 'create_list' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['list/new/$']
The error message Reverse for 'create_list' with keyword arguments '{'pk': ''}' not found. indicates that somewhere you're trying to create a link to the create_list view with incorrect arguments.
In your urls.py file, you don't have any argument for the create_list view (path('new/', CreateList.as_view(), name='create_list'),). However, in your list_list.html, you're trying to create a link to this view with a pk argument in the action attribute of your form:
{% url 'create_list' pk=simpleList.pk %}
Try to add the pk argument in urls.py or remove it from the link in the action attribute of your form.

Multiple file upload the easy way in django

I have to create a form to make a post with fields like Title, description and images. I could successfully create a post with a single image, but when it comes to multiple images, it is not getting saved. Upon research found that i have to use a separate model and form for images. But i cannot see how is it accomplished in the views. So how do i accomplish this the easy way?
Models.py
class news(models.Model):
title = models.CharField(max_length=100)
description= models.TextField(max_length=500)
class newsimages(models.Model):
image = models.ImageField(upload_to='/images/')
related = models.ForeignKey(news,on_delete=models.CASCADE,null=True)
You can do with inline_formset
create a form
class ImageForm(ModelForm):
class Meta:
model = newsimages
exclude = ()
ImageFormSet = inlineformset_factory(news, newsimage, form=ImageForm, extra=1)
You CreateView would be something like:
class NewsCreate(CreateView):
model = news
fields = ['title', 'description']
success_url = some_url
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['images'] = ImageFormSet(self.request.POST or None)
return ctx
def form_valid(self, form):
ctx = self.get_context_data()
images = context['images']
with transaction.atomic():
self.object = form.save()
if images .is_valid():
images.instance = self.object
images.save()
return super().form_valid(form)
in news_form.html
<form method="post" enctype="multipart/form-data">
{{ form.as_p }}
<table>
{{images.management_form}}
{% for f in images.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1,row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Save"/>
</form>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'formset/jquery.formset.js' %}"></script>
<script type="text/javascript">
$('.formset_row').formset({
addText: 'add image',
deleteText: 'remove',
prefix: 'images_set'
});
</script>
You will need to source jquery.formset.js which I think you'll find in django admin static files.

non_form_errors doesn't show

I am working with inlineformset_factory and created a forms.BaseInlineFormSet to override the clean function to make some validations. the validation works and the form isn't accepted but the ValidationError message doesn't appear when the page is reloaded.
here is my form class:
class BaseDetailFormSet(forms.BaseInlineFormSet):
def clean(self):
super(BaseDetailFormSet, self).clean()
if any(self.errors):
return self.errors
for form in self.forms:
product = form.cleaned_data['product']
if form.cleaned_data['quantity_sold'] > product.quantity_in_stock:
raise forms.ValidationError(_('not enough products'))
DetailFormset = inlineformset_factory(Invoices,
InvoiceDetail,
fields=('product', 'quantity_sold'),
widgets= {'product': forms.Select(
attrs={
'class': 'search',
'data-live-search': 'true'
})},
formset=BaseDetailFormSet,
extra=1)
and my html code:
<form class="form-inline" method="post" action="">
{% csrf_token%}
{% include '_layouts/form_snippet.html' %}
<table class="table">
{{inlines.management_form}}
{%for form in inlines.forms%}
{% if forloop.first%}
<thead>
<tr>
{%for field in form.visible_fields%}
<th>{{field.label|capfirst}}</th>
{%endfor%}
{%endif%}
</tr>
</thead>
<tr class="formset_row">
{{ form.non_form_errors }}
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<button type="submit" value="Add" class="btn btn-inverse">{% trans 'Submit Invoice' %}</button>
</form>
any ideas how to show the validation error message or why it isn't shown.
non_form_errors belongs to the formset not the form.
So you can display it with:
{{ formset.non_form_errors }}
Or in your case, since you use the variable inlines:
{{ inlines.non_form_errors }}
Since it belongs to the formset, you should do this outside of the forloop through the forms.
If you have errors on the form that don't belong to any field, then you access these with
{{ form.non_field_errors }}

Newbie - Python Django - NoReverseMatch Error

I have gone through lots of related questions but I am not able to solve this issue so I though I will finally post it, I have an app 'Customers' which will hold a list of customers, currently there are two user levels
1) Customer - If I login as a Customer I would ONLY see my details and I must be able to edit and make changes to my information
2) Advisor - If I login as an Advisor I would see a list of customers and I would be able to make changes to any customer.
To achieve this I have an 'Edit' button when clicked redirects to a 'form' with the particular fields already populated, I can edit and save. Issue arises when I click on this 'Edit' I get this error "NoReverseMatch at /customer/". But when I directly navigate to the form by typing in, "localhost:8000/customer/1/edit" I could see the form.
Here's my views.py
#login_required
def customer_edit(request, cust_number):
# customer = get_object_or_404(Customer, pk=cust_number)
if request.method == "POST":
form = CustomerForm(request.POST)
# form = CustomerForm(request.CUSTOMER, instance=customer)
if form.is_valid():
customer = form.save(commit=False)
customer.cust_number = request.user
customer.updated_date = timezone.now()
customer.save()
return redirect('customer', pk=cust_number)
else:
form = CustomerForm()
return render(request, 'customers/customer_edit.html', {'form': form})
Here's my appname/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^customer/$', views.customer, name='customer'),
url(r'^home/$', views.home, name='home'),
url(r'^customer/(?P<cust_number>\d+)/edit/$', views.customer_edit, name='customer_edit'),
]
Here's a part of my projectname/urls.py
url(r'', include('customers.urls', namespace="customers"))
Here's my customers/forms.py
from django import forms
from .models import Customer
class CustomerForm(forms.ModelForm):
class Meta:
model = Customer
fields = ('cust_number', 'name', 'address', 'city', 'state', 'zipcode', 'email', 'cell_phone',)
Here's my customer_edit.html
{% extends 'customers/base.html' %}
{% block content %}
<h1>Edit Customer</h1>
<form method="POST" class="customer-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock %}
Here's my customer.html
{% extends 'customers/base.html' %}
{% block content %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Eagle Financial</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
</head>
<body>
<style>
body {
background-color: beige;
}
</style>
<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-primary">
<div class="panel-heading">Welcome!</div>
<div class="panel-body">
Eagle Financial Services, your Midwest Financial Services Partner.
</div>
</div>
</div>
</div>
</div>
<div class="row">
<h2 style="padding-left: 15Px">Customer Information</h2>
</div>
<div>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="bg-info">
<th>Customer ID</th>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Primary Email</th>
<th>Cell Phone</th>
<th colspan="3">Actions</th>
</tr>
</thead>
<tbody>
{% for customer in customers %}
<tr>
<td>{{ customer.cust_number }}</td>
<td>{{ customer.name }}</td>
<td>{{ customer.address }}</td>
<td>{{ customer.city }}</td>
<td>{{ customer.state }}</td>
<td>{{ customer.zipcode }}</td>
<td>{{ customer.email }}</td>
<td>{{ customer.cell_phone }}</td>
<td>Update</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
{% endblock %}
Here's my error,
NoReverseMatch at /customer/
Reverse for 'customer_edit' with no arguments not found. 1 pattern(s) tried: ['customer/(?P<cust_number>\\d+)/edit/$']
Request Method: GET
Request URL: http://127.0.0.1:8000/customer/
Django Version: 1.11.1
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'customer_edit' with no arguments not found. 1 pattern(s) tried: ['customer/(?P<cust_number>\\d+)/edit/$']
I have tried trial and errors of namespaces, but not able to solve this. Please guide me. Thanks.
I am using Python - 3.6, Django - 1.11
You are doing wrong in views
customer.cust_number = request.user #Why you assign user to cust_number?
customer.updated_date = timezone.now()
customer.save()
return redirect('customer', pk=cust_number)
Update your view code with below:
from django.core.urlresolvers import reverse
#login_required
def customer_edit(request, cust_number):
# customer = get_object_or_404(Customer, pk=cust_number)
if request.method == "POST":
form = CustomerForm(request.POST)
# form = CustomerForm(request.CUSTOMER, instance=customer)
if form.is_valid():
customer = form.save(commit=False)
customer.cust_number = request.user.pk
customer.updated_date = timezone.now()
customer.save()
return reverse('customers:customer_edit', request.user.pk)
else:
form = CustomerForm()
return render(request, 'customers/customer_edit.html', {'form': form})
Use this in html
<td>Update</td>

Categories