I am pretty new to django I need to keep adding form data in to the html table in same page. I can populate one time but i need to keep adding each time.
refer below gif:
sample data
What I need is i need to add the data i have added second time to populate in the table in second row.
please help me on this
Form.py
from django import forms
class vm_provisioning_form(forms.Form):
name = forms.CharField()
email = forms.EmailField(
)
views.py
from django.shortcuts import render
from django.http import HttpResponse
from Forms import forms
def vm_provisioning(request):
form_vm_provisoning_info = forms.vm_provisioning_form()
hidden_values = []
if request.method == 'POST':
values = []
form_vm_provisoning_info = forms.vm_provisioning_form(request.POST)
if form_vm_provisoning_info.is_valid():
# DO SOMETHING CODE
print("VALIDATION SUCCESS!")
name = form_vm_provisoning_info.cleaned_data['name']
email = form_vm_provisoning_info.cleaned_data['email']
values.append([name, email])
return render(request, 'Forms_template/vm_provisioning/vm_provisioning_form.html', {'forms': form_vm_provisoning_info,'data': values })
return render(request, 'Forms_template/vm_provisioning/vm_provisioning_form.html', {'forms': form_vm_provisoning_info})
form_vm_provisoning_info.html
<!-- templates/vm_provisoning/form_vm_provisoning_info.html -->
<!DOCTYPE html>
{% extends 'Forms_template/base.html' %}
{% block title %}Login in registration{% endblock %}
{% block content %}
<h1> Vm provisoning form</h1>
<div class="container">
<h1>Please Fill details here!</h1>
<form method="POST">
{{ forms.as_p }}
{% csrf_token %}
<section>
<!-- hidden_data= forms.CharField(widget=forms.HiddenInput(), required=False) -->
{% if data %}
<table border="1">
<tr>
<th>Name</th>
<th>email</th>
</tr>
<!-- <p>{{ data }}</p> -->
{% for mapdata in data %}
<!-- <p>{{ mapdata }}</p> -->
<tr>
<td>{{ mapdata.0 }} </td>
<td>{{ mapdata.1 }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</section>
<input type="submit" class='btn btn-primary' value="Submit">
</form>
</div>
{% endblock %}
Take a look at your views. This might be because you are assigning new values list everytime there is a POST request sent, instead try giving it above, also you must send the values list to the GET method also, so it always displays the data.
def vm_provisioning(request):
form_vm_provisoning_info = forms.vm_provisioning_form()
hidden_values = []
values = []
if request.method == 'POST':
form_vm_provisoning_info = forms.vm_provisioning_form(request.POST)
if form_vm_provisoning_info.is_valid():
# DO SOMETHING CODE
print("VALIDATION SUCCESS!")
name = form_vm_provisoning_info.cleaned_data['name']
email = form_vm_provisoning_info.cleaned_data['email']
values.append([name, email])
return render(request, 'Forms_template/vm_provisioning/vm_provisioning_form.html', {'forms': form_vm_provisoning_info,'data': values })
return render(request, 'Forms_template/vm_provisioning/vm_provisioning_form.html', {'forms': form_vm_provisoning_info,'data': values})
Related
I am new to using the Django framework. I am creating a form to take in User input to query a database. I want to display the queried results on the same page, below the from fields. I am able to do the same. However, upon implementing Pagination, and clicking the 'next' link, or trying to sort the results using 'order_by', the queried results disappear from the webpage. How can this be resolved?
Below are my code files:\
views.py:
def get(self, request, *args, **kwargs):
paginated_objects = []
order_by = None
form = QueryForm(request.GET)
button_state = True
if form.is_valid():
max_traj_len = form.data["traj_len_user"]
print(form.data["submit"])
print(max_traj_len)
order_by = request.GET.get('order_by', 'traj_len') ##default order_by is set here
backtrack_flag = form.data["backtrack_user"]
print(backtrack_flag)
queried_objects = list(collection.find({'traj_len':{'$lte':int(max_traj_len)}}))
paginator = Paginator(queried_objects, 25)
page = request.GET.get('page')
paginated_objects = paginator.get_page(page)
button_state = request.GET.get('submit')
return render(request, self.template_name, {'form': form,'object_list': paginated_objects, 'order_by': order_by, 'button_state': button_state})
template.html:
{% extends 'base.html' %}
{% block content %}
<form action='' method='get'>
{% csrf_token %}
<table>{{ form.as_table }}</table>
<input type="submit" name="submit" value="Query">
</form>
{% if button_state == 'Query' %}
<table id="studata">
<thead>
<th>Traj ID</th>
<th>Traj Path</th>
<th>Traj Length</th>
<th>Interpolated_ID</th>
<th>Interpolated Path</th>
<th>Interpolated Path Length</th>
<th>Backtrack</th>
<th>Reached Goal</th>
</thead>
{% for obj in object_list %}<tr>
<script type="text/javascript">
var ele = {{ obj.traj_path }};
var last_ele = ele.pop()
//assuming 0 is the goal trajectory: change if another json is the goal state
if(last_ele == 0){
goal = "True"
}
else{
goal = "False"
}
</script>
<td><a href = '/hoc4/{{ obj.traj_id }}' >{{ obj.traj_id }}</a></td>
<td>{{ obj.traj_path }}</td>
<td>{{ obj.traj_len }}</td>
<td>{{ obj.interpolated_id }}</td>
<td>{{ obj.inter_path }}</td>
<td>{{ obj.inter_path_len }}</td>
<td>{{ obj.backtrack }}</td>
<td><script type="text/javascript">
document.write(goal)
</script>
</td>
</tr>
{% endfor %}
</table>
<div class="pagination">
<span class="step-links">
{% if object_list.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ object_list.number }} of {{ object_list.paginator.num_pages }}.
</span>
{% if object_list.has_next %}
next
last »
{% endif %}
</span>
</div>
{% endif %}
{% endblock %}
forms.py:
class QueryForm(forms.Form):
traj_len_user = forms.IntegerField(min_value=0, required=True)
backtrack_user = forms.BooleanField()
You're doing a lot of extra stuff that seems like you don't even need... You don't need a form for querying anything. You only need whatever's in request.GET and request.POST. You can access them by request.GET.get('name_attribute_of_input'), and so on.
Here's the relevant portion of how to use a Paginator class.
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def get_something(request):
object_list = MyModel.published.all()
tag = None
paginator = Paginator(object_list, 3) # 3 objects on each page
page = request.GET.get('page') # this is getting the 'page' quesry string argument in the url as a GET request, so ?page=whatever_url
try:
my_models = paginator.page(page) # by itself without paginator, object_list would get all my_models and put it on one page. But the paginator object here converts the X objects into pages.
# And those pages are reached by the page variable above that GET's it.
except PageNotAnInteger:
# If page is not an integer, deliver the 1st page
my_models = paginator.page(1)
except EmptyPage:
# If page is out of range deliver last page of results
my_models = paginator.page(paginator.num_pages)
return render(request, 'blog_app/list.html', {'page': page, 'my_models': my_models})
And your template would have something like this in it:
{% if page.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page.number }} of {{ page.paginator.num_pages }}.
</span>
{% if page.has_next %}
Next
{% endif %}
(sorry for my bad english)
I need to delete an object, but directly from a list of the objects that y have in my template.
I have a work orders, that have spare parts but i don't know how to create the deleteview for the spare parts using only a buton in the detailview of the work order. The idea is that the user make click in the Delete button.
This is the model of the Spare Parts
class OrderSparePart(models.Model):
# Relations
workorder = models.ForeignKey(
WorkOrder,
verbose_name=_('order'),
)
# Attributes - Mandatory
spare_part = models.CharField(
max_length=80,
verbose_name=_('spare part'),
)
# Attributes - Optional
price = models.DecimalField(
max_digits=6,
decimal_places=2,
null=True,
blank=True,
verbose_name=_('price'),
)
# Object Manager
# Custom Properties
# Methods
def get_absolute_url(self):
return reverse('work_orders:detail', kwargs={'order_id': self.workorder.id})
# Meta and String
class Meta:
verbose_name = _("order spare part")
verbose_name_plural = _("order spare parts")
This is where is showed in the template
{% if spare_parts %}
<table class="table">
<thead>
<tr>
<th>{% trans "Spare Part" %}</th>
<th>{% trans "Price" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
{% for part in spare_parts %}
<tr>
<td><i class="fa fa-gear"></i> {{ part.spare_part }}</td>
{% if part.price %}
<td>$ {{ part.price }}</td>
{% else %}
<td></td>
{% endif %}
<td><i class="fa fa-trash"></i></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>NO HAY REPUESTOS ASENTADOS AÚN</p>
{% endif %}
The the idea is use the to delete the spare part.
how i have to make the deleteview and the link to this???
Thanks!
here in fa fa-thrash pass the id and the URL as I did it:-
{% if spare_parts %}
<table class="table">
<thead>
<tr>
<th>{% trans "Spare Part" %}</th>
<th>{% trans "Price" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
{% for part in spare_parts %}
<tr>
<td><i class="fa fa-gear"></i> {{ part.spare_part }}</td>
{% if part.price %}
<td>$ {{ part.price }}</td>
{% else %}
<td></td>
{% endif %}
<td></i></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>NO HAY REPUESTOS ASENTADOS AÚN</p>
{% endif %}
ur url would be sonething like that:
url(r'^delete/(?P<part_id>[0-9]+)/$', view.function, name='delete_view'),
in ur view:
def function(request,part_id =None):
object = YourModel.objects.get(id=part_id)
object.delete()
return render(request,'ur template where you want to redirect')
In your html template inside for loop use the form tag inside <td> to create delete button as below (css class will work if you are using bootstrap3):
<form action="{% url 'delete_view' pk=part.pk %}" method="POST">
{% csrf_token %}
<input class="btn btn-default btn-danger" type="submit" value="Delete"/>
</form>
add urlpattern in urls.py
url(r'^delete-entry/(?P<pk>\d+)/$', views.DeleteView.as_view(), name='delete_view'),
delete view will be like below in views.py
class DeleteView(SuccessMessageMixin, DeleteView):
model = OrderSparePart
success_url = '/'
success_message = "deleted..."
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
name = self.object.name
request.session['name'] = name # name will be change according to your need
message = request.session['name'] + ' deleted successfully'
messages.success(self.request, message)
return super(DeleteView, self).delete(request, *args, **kwargs)
Note: import necessary imports shown in links or you need not to worry if you are using IDE such as pyCharm it will prompt you which import to make.
My solutions works best for django 4.0.3 and is the combination of gahan and Abi waqas answers. Use this one if you are using django 3 or above
Add the following to views.py
def delete_object_function(request, id):
# OrderSparePart is the Model of which the object is present
ob = OrderSparePart.objects.get(id=id)
ob.delete()
return redirect('page-delete.html') # for best results, redirect to the same page from where delete function is called
Add the following to urls.py
path('page-delete/<int:id>', views.delete_object_function, name='delete_object'),
Add the following code to the django template from where the delete function is to be called.
Let's say page-delete.html
<form action="{% url 'delete_object' id=part.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" type="submit" ><i class="fa fa-trash"></i></button>
</form>
This works as I've used this solution in my own code.
Ok guys, I got two different models:
class topic(models.Model):
learningObjectivesTopic = models.ManyToManyField(learningObjective, verbose_name = "Lernziel")
topic = models.TextField(verbose_name = 'Thema')
and
class learningObjective(models.Model):
learningObjectives = models.TextField(verbose_name = 'Lernziel')
Pretty basic. My aim is to create entrys for the attribute "topic" and then refer to them when I want to create a new learning objective. My views obviously don't work the way I want them to work but I will post them to explain later on what my aim was.
from django.shortcuts import render
from programm.models import *
from django.contrib.auth.decorators import login_required
#login_required(login_url='login')
def lernziel(request):
return render(request, 'lernziel.html', {'topic': topic.objects.all()})
#login_required(login_url='login')
def create_lernziel(request):
neuesLernziel=learningObjective(learningObjectives=request.POST["Lernziel"])
neuesLernziel.save()
neuesLernziel_Topic=topic(topic=request.POST["Thema"])
neuesLernziel_Topic.save()
neuesLernziel_Topic.learningObjectivesTopic.add(neuesLernziel)
return render(request, 'lernziel.html', {'topic': topic.objects.all()})
#login_required(login_url='login')
def themen(request):
return render(request, 'themen.html', {'thema': topic.objects.all()})
#login_required(login_url='login')
def create_themen(request):
neueThemen=topic(topic=request.POST['Thema'])
neueThemen.save()
return render(request, 'themen.html', {'thema': topic.objects.all()})
I thought with this line:
neuesLernziel_Topic.learningObjectivesTopic.add(neuesLernziel)
I could refer a learning objective, which I am about to create, to and existing topic. But how it seems, my django view just creates a new entry with a new id instead of using an old entry with the same value and an old id. To make it more clear: I have: topic1 and topic2. And I want to refer now 4 learning objectives. For instance lObj 1 and 3 to topic 1 and lObj 2 and 4 to topic 2. What happens is, that at the moment django created 4 new entrys in the topic table. It now contains 3 entrys with the value topic1 and 3 entrys with the value topic2. It should have been still 2 entrys and in the manytomany table it should use the odl id's. If you need more information or if something is unclear please write it :)
Btw I am receiving the data from these two templates:
lernziel.html:
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:"de-de" }}" >
<head>
<h1 align = "center">Lernziele</h1>
</head>
<body>
<form action="{% url 'create_lernziel' %}" method="post">
{% csrf_token %}
<br>Hallo Benutzer: {{ user.username }}</br>
Lernziel: <textarea name="Lernziel" rows="3" cols="45" ></textarea>
<p>
<select name="Thema" size="3">
{% for topic_ in topic %}
<option>{{ topic_.topic }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="Absenden" />
</form>
<table border="1">
<th>Lernziel</th>
<th>Thema</th>
{% for topic_ in topic %}
<tr>
{% for lObj in topic_.learningObjectivesTopic.all %}
<td>{{ lObj }}</td>
{% endfor %}
<td>{{ topic_.topic }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
and themen.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<br>Hallo Benutzer: {{ user.username }}</br>
<form action="{% url 'create_themen' %}" method="post">
{% csrf_token %}
<br>Thema: <textarea name="Thema" rows="3" cols="45"></textarea></br>
<input type="submit" value="Absenden" />
</form>
</br>
<table border="1">
<th>Thema</th>
{% for thema_ in thema %}
<tr>
<td>{{ thema_.topic }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
The problem is not with that line: it is with the previous two lines, which explicitly create a new Topic. If you want to associate your objective with an existing Topic, you need to use get to get it from the database, rather than instantiating a new one and calling save().
neuesLernziel=learningObjective(learningObjectives=request.POST["Lernziel"])
neuesLernziel.save()
neuesLernziel_Topic = Topic.objects.get(topic=request.POST['Thema'])
neuesLernziel_Topic.learningObjectivesTopic.add(neuesLernziel)
You probably want to post/query by an ID, rather than the text of "topic", though.
OK, so this is my first time using formsets. I am trying to create a table that I can dynamically add rows to and fill out each row, then submit and have Django put them all in the database. Every time I submit it only adds the first form.
File views.py:
#main_context_wrapper
def bacteriaForm2(request,context):
if not request.user.is_authenticated():
#If user isn't authenticated, then just redirect to login
return HttpResponseRedirect('/login/')
BacteriaFormSet = formset_factory(BacteriaForm)
if request.POST:
bacteriaformset = BacteriaFormSet(request.POST, request.FILES)
if bacteriaformset.is_valid():
context["error"] = ""
for form in bacteriaformset:
form.save()
return HttpResponseRedirect('/')
else:
context["error"] = "validation"
context["bacteriaformset"] = BacteriaFormSet
context.update(csrf(request))
return render_to_response('bacteriaForm.html', context)
else:
#The request was a GET, add the form to the context
context["bacteriaformset"] = BacteriaFormSet()
#Add all siteInfo objects to allow for dynamic site info drop down menus
siteInfo = SiteInfo.objects.all()
context["siteInfo"] = siteInfo
return render(request, "bacteriaForm.html", context)
Template:
{% extends "inherited/main.html" %}
{% block content %}
<h1> Bacteria Entry Form </h1>
<form action='/bacteriaForm/' method="post">{% csrf_token %}
{{bacteriaformset.management_form}}
{% if error == "validation" %}
<div class="alert alert-danger">
<p>
<strong>Error: </strong>Form not completed properly.
</p>
</div>
{% endif %}
<table id="id_forms_table">
<tr>
{% for field in bacteriaformset.forms.0 %}
{% if not field.is_hidden %}
<th>{{ field.label }}</th>
{% endif %}
{% endfor %}
</tr>
{% for f in bacteriaformset.management_form %}
{{ f }}
{% endfor %}
{% for f in bacteriaformset.forms %}
<tr id="{{ f.prefix }}-row" class="dynamic-form">
{% for field in f %}
{% if not field.is_hidden %}
<td>
{{ field.errors }}
{{ field }}
</td>
{% else %}
<td valign="bottom">{{ field }}</
{% endif %}
{% endfor %}
<td{% if forloop.first %} class="hidden"{% endif %}>
<a id="remove-{{ form.prefix }}-row" href="javascript:void(0)" class="delete-row">delete</a>
</td>
</tr>
{% endfor %}
<tr>
<td colspan="4">add property</td>
</tr>
</table>
<div>
<input type="submit" value="submit" />
</div>
</form>
<script>
$(function () {
$('.add-row').click(function() {
return addForm(this, 'form');
});
$('.delete-row').click(function() {
return deleteForm(this, 'form');
});
});
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+)');
var replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
var row = $('.dynamic-form:first').clone(true).get(0);
$(row).removeAttr('id').insertAfter($('.dynamic- form:last')).children('.hidden').removeClass('hidden');
$(row).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, formCount);
$(this).val('');
});
$(row).find('.delete-row').click(function() {
deleteForm(this, prefix);
});
$('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
return false;
}
function deleteForm(btn, prefix) {
$(btn).parents('.dynamic-form').remove();
var forms = $('.dynamic-form');
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
for (var i=0, formCount=forms.length; i<formCount; i++) {
$(forms.get(i)).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, i);
});
}
return false;
}
$("#id_date").datepicker();
</script>
{% endblock %}
File Models.py
class BacteriaEntry(models.Model):
"""
A bacteria entry contains information about a test set's
bacteria levels at a specific time. BacteriaEntry utilizes the
Djano model.
"""
siteNumber = models.IntegerField()
date = models.DateField()
sampleNumber = models.IntegerField(primary_key=True)
ecoliRawCount = models.IntegerField(null=True)
ecoli = models.DecimalField(decimal_places=10, max_digits=20, null=True)
ecoliException = models.IntegerField(null=True)
coliformRawCount = models.IntegerField(null=True)
coliform = models.DecimalField(decimal_places=10, max_digits=20, null=True)
coliformException = models.IntegerField(null=True)
comments = models.CharField(max_length=2000, null=True)
"""Returns the sample number of the Bacteria Entry"""
def __unicode__(self):
return smart_unicode(self.sampleNumber)
Here is some post data
<QueryDict: {u'form-0-date': [u'02/24/2014'], u'form-0-comments': [u'65'], u'form- MAX_NUM_FORMS': [u'1000', u'1000'], u'form-0-coliformRawCount': [u'5'],
u'form-0-coliform': [u'65'], u'form-0-ecoliException': [u'56'], u'form-TOTAL_FORMS': [u'1', u'1'], u'form-0-sampleNumber': [u'1554'], u'form-0-ecoliRawC
ount': [u'35'], u'form-0-coliformException': [u'56'], u'form-INITIAL_FORMS': [u'0', u'0'], u'csrfmiddlewaretoken': [u'VSnaJCW6R9z8iEKib46cHuBJ6AKTPPUT'],
u'form-0-ecoli': [u'51'], u'form-0-siteNumber': [u'100']}>
I'm not exactly sure where my problem is. I have spent a lot of time trying to figure this out. I am not sure what is wrong.
You're not printing formset.non_form_errors, or form.non_field_errors in any of the child forms, in your template - there's probably something in one of those that is causing validation to fail.
I should also point out that there is no need to instantiate the form separately from the formset. It makes no sense to create a separate BacteriaForm instance and pass it to the template, then validate it on post: that's what the formset is for, after all.
I'm a bit confused with this, not sure why you need both a Form and a FormSet, especially because the FormSet contains the same Forms as is the separate Form...
But if that is the case, then you should use prefix on the Form and/or on the FromSet:
bacteriaForm = BacteriaForm(request.POST, prefix='the_one_bacteria')
bacteriaformset = BacteriaFormSet(request.POST, request.FILES, prefix='bacterias')
and also in the else: part of the View.
Pardon my plural.
I've been playing around with Django forms and it's a bit of a headache. I came to a point where I can display my form properly but I only want to edit part of it's data, not all of them.
Specifically: I have a Product model that has a title and a featured bool field. I want a form that displays all the products names with a tickbox next to it. The user is able to edit the featured property of each Product on the same form, but only that! My problem is that with the current setup, the displayed title is also an input field, not a simple text. If I change the template to display {{ productForm.title.value }} instead of {{ productForm.title }} it displays it as a text but the form failes the validation (It requires the title to have a value, since it cannot be null).
Model is plain simple, title and featured fields with CharField and BooleanField types. Validation branch is also not taken care of in the sample but "is_valid()" returns false.
views.py
def featured_product(request):
FeaturedProductFormSet = modelformset_factory(Product, fields=('title', 'featured'))
if request.method == "POST":
productForms = FeaturedProductFormSet(request.POST)
if productForms.is_valid():
productForms.save()
return redirect('/admin/')
else:
productForms = FeaturedProductFormSet()
return render_to_response(
'vetco_app/featured_products.html',
{
'productForms': productForms,
},
context_instance=RequestContext(request)
)
featured_products.html
<form action="" method="post">
<table>
<thead>
<th>
Termék neve
</th>
<th>
Kiemelt
</th>
</thead>
<tbody>
{% for productForm in productForms %}
{% if not forloop.last %}
<tr>
<td>
{{ productForm.id }}
{{ productForm.title }}
</td>
<td>
{{ productForm.featured }}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<p>
{{ productForms.management_form }}
{% csrf_token %}
<button type="submit" name="action" value="Save">Save</button>
</p>
How to make it display only the text of the title without the need to validate it?
Simply provide context:
from django.template import RequestContext
context = RequestContext(request, {"your_model":your_model")
now in templates just write:
{{ your_model.some_attribute }}