Rendering a FormSet in Django - python

I want to create a FormSet which allows users to add forms as needed. However, when I render the page, I am receiving an error:
ValueError: The view website.views.presales didn't return an HttpResponse object.
It returned None instead.
I would like to always render the form blank. Please let me know if any other information is needed, thanks!
Note: cwObj.get_opportunities() is an API call to create an object from a JSON response to populate the select_opportunity dropdown. Lastly, I am using AJAX to dynamically calculate the value of the span Total using data-total-url="{% url 'presales_total' %}".
forms.py
class PresalesForm(forms.Form):
class Meta:
model = Presales
fields = ('selected_opportunity', 'task_description', 'hours', 'selected_engineer_level', 'total_cost')
views.py
def presales(request):
my_opportunities = cwObj.get_opportunities()
PresalesFormSet = formset_factory(PresalesForm, extra=1)
if request.method == 'POST':
presales_formset = PresalesFormSet(request.POST)
if presales_formset.is_valid():
for presales_form in presales_formset:
selected_opportunity = request.POST.get('selected_opportunity')
task_description = request.POST.get('task_description')
hours = request.POST.get('hours')
select_engineer_level = request.POST.get('select_engineer_level')
else:
presales_formset = PresalesFormSet(initial="None")
context = {'presales_formset': presales_formset, 'my_opportunities': my_opportunities}
return render(request, 'website/presales.html', context)
presales.html
<form action="{% url 'presales' %}" method="post" name="presalesForm" id="presalesForm" data-total-url="{% url 'presales_total' %}">
{% csrf_token %}
{{ presales_formset.management_form }}
{% for presales_form in presales_formset %}
<div class="field">
<label class="label is-large">Create Task</label>
</div>
<div class="section">
<div class="field">
<label class="label">Opportunity</label>
<div class="select">
<select name="select_opportunity" id="select_opportunity">
<option value="">Opportunity</option>
{% for opportunity in my_opportunities %}
<option name="selected_opportunity" id="selected_opportunity" value="{{ opportunity.name }}">{{ opportunity.name }}</option>
{% endfor %}
</select>
</div>
</div>
<label class="label">Task Description:</label>
<div class="field">
<div class="control">
<input class="input" name="task_description" id="task_description" placeholder="Task Description">
</div>
</div>
<label class="label">Hours</label>
<div class="field">
<div class="control">
<input class="input" name="hours" id="hours" placeholder="Hours">
</div>
</div>
<label class="label">Engineer Level:</label>
<div class="field">
<div class="select">
<select name="select_engineer_level" id="select_engineer_level">
<option value="">Engineer Level</option>
<option value="PM">PM</option>
<option value="Solutions Technician">Solutions Technician</option>
<option value="Solutions Engineer">Solutions Engineer</option>
<option value="Senior Solutions Engineer">Senior Solutions Engineer</option>
<option value="Solutions Architect">Solutions Architect</option>
</select>
</div>
</div>
</div>
<div class="field">
<div class="control">
<button class="button is-info" type="button">Add Task</button>
</div>
</div>
{% endfor %}
<span class="label is-medium is-pulled-right" id="total_cost">Total: {{ total }}</span>
</form>

Your view does NOT return an HttpResponse in all cases, which is an error. This happend when request.method is different than POST and when the formset is not valid.
This is pretty easy to spot when removing most of the code and just leaving the conditional statements:
def presales(request):
if request.method == 'POST':
if presales_formset.is_valid():
...
return render(request, 'website/presales.html', context)
You have to return other HttpResponse's in the other cases as well to solve this error.
For example, you could un-indent the line return render(... 2 levels, so that the view always returns the template.

Related

Why aren't changes saved when editing a Django product?

Created a website with products. I need to make a window for editing them on the site in order to change the manufacturer and other characteristics. This must be done in a pop-up window. I have data displayed, I change it, but nothing changes when I save it. How can this problem be solved.
My vievs:
def parts(request):
added = ''
error = ''
PartAllView = Part.objects.order_by('-id')
if request.method == 'POST' and 'parts_add' in request.POST:
form = PartForm(request.POST, request.FILES)
if form.is_valid():
form.save()
added = 'Добавлено'
else:
error = 'Данная запчасть уже добавлена'
if request.method == 'POST' and 'parts_edit' in request.POST:
PartPost = int(request.POST['parts_edit'])
PartID = Part.objects.get(id=PartPost)
if PartID:
PartID.save()
added = 'Запчасть успешно отредактирована'
else:
error = 'Ошибка редактирования'
form = PartForm()
data = {
'added': added,
'error': error,
'form': form,
'PartAllView': PartAllView,
}
return render(request, 'kross/parts.html', data)
My HTML:
{% if PartAllView %}
{% for el in PartAllView %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal fade" id="partEdit{{ el.id }}">
<div class="modal-dialog modal-dialog-centered text-center" role="document">
<div class="modal-content modal-content-demo">
<div class="modal-header">
<h6 class="modal-title">Добавление запчасти</h6><button aria-label="Close" class="btn-close"
data-bs-dismiss="modal"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div class="row row-sm">
<div class="col-lg-6">
<div class="form-group">
<input type="text" class="form-control" name="brand" value="{{ el.brand }}">
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<input type="text" class="form-control" value="{{ el.number }}">
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<input type="text" class="form-control" value="{{ el.name }}"><br>
<input type="textarea" class="form-control" rows="2" value="{{ el.description }}">
</div>
</div>
</div>
{{ el.analog }}
...
You can use updateView to edit an existing data in your website by simply:
from django.views.generic.edit import UpdateView
From MyApp models import #Model
class editview(UpdateView):
model = #Your Model You want to edit
fields = [#Add the fields you want to edit]
template_name = 'edit.html'
success_url = ('Home')
In your edit Template add:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
I hope it help.

Django-Vue error "Failed to mount app: mount target selector returned null."

Thanks for looking into my problem, I am a beginner with Django and Vue your assistance with this wil be extremely helpful. I am working on a Job portal and created the job search functionality in Django as backend for the same I have an app called job into my Django project. The browser Js console gives this error Failed to mount app: mount target selector returned null. For this app I have an add job view, through which an employer adds the jobs. For this I'm using Vue for validation and showing any errors if any non-null fields are not entered by the employer account. So this is not how it was supposed to look,Unexpected results snap shot so as you can see it wasn't supposed to give me [[error]] and company_size instead The company size is missing as per the Vue AddJobApp, given below. Also if were to add # within mount-function-createapp within Vue-AddJobApp, the page entirely disappears (blank page). what am I doing wrong here?
adding # in AddJob.mount() function is making the page go blank a
Add job template
{% extends 'core/base.html' %}
{% block content %}
<div id="add-job-app">
<h1 class="title"> Add Job</h1>
<form action="." method="POST" v-on:submit="validateForm">
{% csrf_token %}
{% if form.errors %}
{% for error in form.errors %}
<div class="notification is-danger">
{{ error }}
</div>
{% endfor %}
{% endif %}
<div class="notification is-danger" v-if ="error.length" >
<p v-for="error in errors" >
[[ error ]]
</p>
</div>
<div class="field">
<label for="">Title</label>
<div class="control">
<input class="input" type="text" name="title" id="id_title" v-model= "title">
</div>
</div>
<div class="field">
<label for="">Short description</label>
<div class="control">
<textarea name="short_description" id="id_short_description" class="textarea" v-model= "short_description" ></textarea>
</div>
</div>
<div class="field">
<label for="">Long description</label>
<div class="control">
<textarea name="long_description" id="id_long_description" class="textarea" v-model= "long_description" ></textarea>
</div>
</div>
<div class="field">
<label for="">Company name</label>
<div class="control">
<input class="input" type="text" name="company_name" id="id_company_name" v-model= "company_name" >
</div>
</div>
<div class="field">
<label for="">Company address</label>
<div class="control">
<input class="input" type="text" name="company_address" id="id_company_address" v-model= "company_address">
</div>
</div>
<div class="field">
<label for="">Company zipcode</label>
<div class="control">
<input class="input" type="text" name="company_zipcode" id="id_company_zipcode" v-model= "company_zipcode">
</div>
</div>
<div class="field">
<label for="">Company place</label>
<div class="control">
<input class="input" type="text" name="company_place" id="id_company_place" v-model= "company_place">
</div>
</div>
<div class="field">
<label for="">Company Country</label>
<div class="control">
<input class="input" type="text" name="company_country" id="id_company_country" v-model= "company_country">
</div>
</div>
<div class="field">
<label for="">Company Size</label>
<div class="control">
<div class="select">
<select name="company_size" v-model = "company_size">
<option value="">Choose Size</option>
<option value="size_1_9">1-9</option>
<option value="size_10_49">10-49</option>
<option value="size_50_99">50-99</option>
<option value="size_100">100+</option>
</select>
</div>
</div>
</div>
<div class="field">
<div class="control">
<button class="button is-success">Submit</button>
</div>
</div>
</form>
</div>
{% endblock %}
{% block scripts %}
<script >
const AddJobApp = {
data() {
return {
title:'',
company_name:'',
short_description:'',
company_size:'',
errors:[]
}
},
delimiters:['[[',']]'],
methods :{
validateForm(e){
this.errors = []
if( this.title ===''){
this.errors.push('The title field is missing')
}
if( this.short_description ===''){
this.errors.push('The short description field is missing')
}
if( this.company_name ===''){
this.errors.push('The company name field is missing')
}
if( this.company_size ===''){
this.errors.push('The company size is missing')
}
if(this.errors.length){
e.preventDefault()
return false
}else{
return true
}
}
}
}
Vue.createApp(AddJobApp).mount('add-job-app');
</script>
{% endblock %}
my views.py file inside of job app
from apps.job.forms import AddJobForm, ApplicationForm
from django.shortcuts import redirect, render
from .models import Job
from django.contrib.auth.decorators import login_required
from apps.notification.utilities import create_notification
def job_detail(request,job_id):
job = Job.objects.get(pk=job_id)
return render(request, 'job/job_detail.html',{'job':job})
def search(request):
return render(request,'job/search.html')
#login_required
def apply_for_job(request,job_id):
job = Job.objects.get(pk=job_id)
if request.method=='POST':
form = ApplicationForm(request.POST)
if form.is_valid():
application = form.save(commit=False)
application.job = job
application.created_by = request.user
application.save()
create_notification(request, job.created_by ,'application',extra_id=application.id)
return redirect('dashboard')
else:
form = ApplicationForm()
return render(request,'job/apply_for_job.html',{'form':form,'job':job})
#login_required
def add_job(request):
if request.method=='POST':
form = AddJobForm(request.POST)
if form.is_valid():
job = form.save(commit=False)
job.created_by = request.user
job.save()
return redirect('dashboard')
else:
form = AddJobForm()
return render(request,'job/add_job.html',{'form':form})

CSRF middleware token missing?

I'm novice adapting a simple address book database program using Django from a course I've done on Codemy.
I have a page where I enter the names, surnames etc together with a DELETE and EDIT button next to each address. There's no problem when I click the EDIT button (the form populates automatically and takes me to website/edit1,2,3,4 etc/), but when I click the 'edit' button after editing the addressee info, I get the error as below. The btn1 is the name="btn1" of the button as indicated.
GET /edit/3?csrfmiddlewaretoken=b4IkMxxxxxxxxxxxDHrDIgRnjvEWr53rL&**btn1**=140 HTTP/1.1" 200 5751
Here is my views file
from django.shortcuts import render, redirect
from .models import List
from .forms import ListForm
from django.contrib import messages
from django.http import HttpResponseRedirect
def home(request):
all_items = List.objects.all
return render(request, 'home.html', {'all_items': all_items})
def about(request):
return render(request, 'about.html', {})
def edit(request, item_id):
if request.method =='POST':
item = List.objects.get(pk=item_id)
form = ListForm(request.POST or None, instance=item)
if form.is_valid():
form.save()
messages.success(request, ('Item Had Been Edited'))
return redirect('home')
else:
item = List.objects.get(pk=item_id)
return render(request, 'edit.html', {'item': item})
def delete(request, item_id):
item = List.objects.get(pk=item_id)
item.delete()
return redirect('home')
...And here is the edit.html file
{% extends 'base.html' %}
{% block title %}To-Do-List | Edit {% endblock %}
{% block content %}
{% if item %}
{{ item.item }}
<form class="needs-validation" novalidate>
{% csrf_token %}
<div class="form-row">
<div class="col-md-6 mb-3">
<label for="validationCustom01">First name</label>
<input type="text" class="form-control" id="validationCustom01" value="{{ item.First_name }}" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
<div class="col-md-6 mb-3">
<label for="validationCustom02">Last name</label>
<input type="text" class="form-control" id="validationCustom02" value="{{ item.Surname }}" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6 mb-3">
<label for="validationCustom03">Street</label>
<input type="text" class="form-control" value="{{ item.Street }}" id="validationCustom03" required>
<div class="invalid-feedback">
Please provide a valid city.
</div>
</div>
<div class="col-md-3 mb-3">
<label for="validationCustom03">Town</label>
<input type="text" class="form-control" value="{{ item.Town }}" id="validationCustom03" required>
<div class="invalid-feedback">
Please provide a valid city.
</div>
</div>
<div class="col-md-3 mb-3">
<label for="validationCustom05">Province</label>
<input type="text" class="form-control" value="{{ item.Province }}" id="validationCustom05" required>
<div class="invalid-feedback">
Please provide a valid zip.
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-3 mb-3">
<label for="validationCustom05">Postal code</label>
<input type="text" class="form-control" value="{{ item.Postal_code }}" id="validationCustom05" required>
<div class="invalid-feedback">
Please provide a valid zip.
</div>
</div>
</div>
<button class="btn btn-primary" type="submit" type="hidden" value="" name='btn1'>Edit</button>
</form>
<script>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function() {
'use strict';
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
</script>
{% endif %}
{% endblock %}
I cannot locate an issue with the CSRF token. it is included just like the tutorial on the edit.html page. Not even sure if the issue is with the token?
I've gone through the tutorial time and again and cannot see an issue.
I'm a noob, so any info would be great!
Normally, when you save information after editing it in a form, you should "post" your data to the server.
It appears your form method is not set which default to get. It should be set to post.
<form method="post">...</form>
This being said, your view should also be configured accordingly. Without more details, it is hard to provide deeper answer.

Django display json data table

I'm currently unable to display json data from solr that crawls twitter API tweets.
I would like to display them in a table form so that it would be easier to view and add additional UI stuff later.
Here's my code:
my views.py
def my_view(request):
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
gotName = form.cleaned_data['your_name']
gotEmotion = form.cleaned_data['emotion']
gotWords = form.cleaned_data['words']
url = 'http://localhost:8983/solr/gettingstarted/query?q=id:' + gotName
r = requests.post(url, data={'id': gotName})
return render(request, 'index.html', {"table_data" : ??? })
#return render(request, 'index.html', {"mydata": mydata})
else:
not_working = "not working"
return render(request, 'index.html', {'text2': not_working })
my index.html table part:
<table>
# insert table formatting here
</table>
full index.html body:
<body>
{% load static %}
<img src="{% static "/templates/happybird.jpg" %}"/>
<h1 style="text-align:center;">Emotional Tweets</h1>
<div class="container">
<div class="row">
<div class="col-md-12" >
<div class="input-group" id="adv-search">
<form action="/search/my_view/" method="POST">
{% csrf_token %}
{{ form }}
<div>
<input id="your_name" type="text" class="form-control" name="your_name" placeholder="Search for Tweets" value="{{ current_name }}" />
<br>
</div>
<div class="form-group">
<label for="filter">Filter by</label>
<select class="form-control">
<option value="0" selected>All Tweets</option>
<option value="1">Excited</option>
<option value="2">Happy</option>
<option value="3">Neutral</option>
<option value="4">Sad</option>
<option value="5">Angry</option>
</select>
</div>
<div class="form-group">
<label for="contain">Contains the words</label>
<input id="words" class="form-control" type="text" name="words" value="{{ current_words }}" />
</div>
<input type="submit" value="OK">
</form>
</div>
</div>
</div>
</div>
</div>
<p>{{ text2 }}</p>
<p>{{ text3 }}</p>
<table>
# insert table formatting here ???
</table>
<script type="text/javascript">
</script>
</body>
currently the response r.text displays the raw json in text form for the query a* from my solr crawled data.
so I need help with processing the json data into a table format to display in the html.

Django Form Field Custom attribute assignment and use in template

I am trying to generate a form dynamically and want to assign indentation of form fields. I am trying to assign an custom attribute offset to forms.CharField in subclass. I plan to use this logic to create a form dynamically from an xml file, where the fields would be indented based on the depth of the node.
I am unable to retrieve the value of offset while rendering the template and hence unable to assign the margin-left style parameter. The final html output is also shown.
Can someone please help. I have searched some other answers on this site where it appears that arbitrary attributes can be assigned and retrieved in template. e.g.as in thread here where an arbitrary label_class attribute is assigned
My forms.py file :
class MyCharField(forms.CharField):
def __init__(self, *args, **kwargs):
self.offset = kwargs.pop('offset', 0)
super(MyCharField, self).__init__(*args, **kwargs)
class MyDynamicForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyDynamicForm, self).__init__(*args, **kwargs)
self.fields["Field_A"] = MyCharField(label="Input A", offset="5")
self.fields["Offset_Field_B"] = MyCharField(label="Input B", offset="50")
My Views.py looks like this:
class MyDynamicView(View):
template_name = 'demo/myform.html'
form_class = MyDynamicForm
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
My template file using bootstrap looks like this:
{% extends 'demo/base.html' %}
{% load bootstrap3 %}
{% block content %}
<form role="form" method="post">
{% csrf_token %}
{% for field in form %}
<div class="form-group bootstrap3-required">
<label class="col-md-3 control-label " style = "margin-left: {{field.offset}}px" for="{{ field.name }}">{{ field.label}}</label>
<div class="col-md-9">
<input class="form-control" id="id_{{field.name}}" name="{{ field.name }}" placeholder="{{field.label}}" style="margin-left:{{field.offset}}px" title="" required="" type="text"/>
</div>
</div>
{% endfor %}
{% buttons submit='OK' reset='Cancel' layout='horizontal' %}{% endbuttons %}
</form>
{% endblock %}
The html output is:
<form role="form" method="post">
<input type='hidden' name='csrfmiddlewaretoken' value='lTy0rc2r9KNiNNPosUoriUlNzYBpgoVpael1MYLOczFECO7H7LXdES6EGBhUoXx0' />
<div class="form-group bootstrap3-required">
<label class="col-md-3 control-label " style = "margin-left: px" for="Field_A">Input A</label>
<div class="col-md-9">
<input class="form-control" id="id_Field_A" name="Field_A" placeholder="Input A" style="margin-left:px" title="" required="" type="text"/>
</div>
</div>
<div class="form-group bootstrap3-required">
<label class="col-md-3 control-label " style = "margin-left: px" for="Offset_Field_B">Input B</label>
<div class="col-md-9">
<input class="form-control" id="id_Offset_Field_B" name="Offset_Field_B" placeholder="Input B" style="margin-left:px" title="" required="" type="text"/>
</div>
</div>
<div class="form-group"><label class="col-md-3 control-label"> </label><div class="col-md-9"><button class="btn btn-default" type="submit">OK</button> <button class="btn btn-default" type="reset">Cancel</button></div></div>
</form>
It not necessary to instantiate from CharField for that. Probably such initialization of the field in form will be enough for you:
field_a = forms.CharField('Input_A',
widget=forms.TextInput(attrs={'placeholder': 'Input_A', 'style': 'margin-left: 50px'}))

Categories

Resources