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.
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 %}
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})
My aim is to create a matrix with individual editable fields. Since different people should only be allowed to edit certain fields I thought about creating an object called CellCE and an object level permission.
my models.py
class CellCE(models.Model):
row = models.ForeignKey('Descriptor',related_name='activecell', on_delete=models.CASCADE)
col = models.ForeignKey('Descriptor',related_name='passivecell', on_delete=models.CASCADE)
val = models.IntegerField(default=0)
project = models.ForeignKey('Project', on_delete=models.CASCADE, default='1')
#permission for Cells
class Meta:
permissions = (
("edit_cellCE", "Has permission to edit value of Cause and Effect cell"),
)
#classmethod
def create(cls, row, col, project):
CellCE = cls(row=row, col=col, project=project)
CellCE.save()
return CellCE
my views.py
def phase2(request, id):
projectname = get_object_or_404(Project, pk=id)
projectid = id
project = Project.objects.get (id=projectid)
projectdescriptors = Descriptor.objects.filter( project=projectid)
for Descriptor.id in projectdescriptors:
row = Descriptor.id
for Descriptor.id in projectdescriptors:
col = Descriptor.id
if CellCE.objects.filter(row=row, col=col, project=project).exists():
pass
else:
obj = CellCE.create(row, col, project)
CellCElist = CellCE.objects.filter(project= project)
context = {'CellCElist': CellCElist, 'projectname': projectname, 'projectid': projectid, 'projectdescriptors': projectdescriptors}
return render(request, 'szenario/phase2.html', context)
my template
<table>
{% for drow in projectdescriptors %}
{% if forloop.first %}
<tr>
<th align="left">Descriptors</th>
{% for value in projectdescriptors %}
<th>{{value}}</th>
{% endfor %}
</tr>
{% endif %}
<tr>
<th align="left">{{drow}}</th>
{% for dcol in projectdescriptors %}
<td align="center">
{% if forloop.parentloop.counter == forloop.counter %}
-
{% else %}
{% for CellCE in CellCElist %}
{% if CellCE.col == dcol %}
{% if CellCE.row == drow %}
Value =
{{CellCE.val}}
{% endif %}
{% endif %}
{% endfor %}
<form method="post">
{% csrf_token %}
<input type="submit" value="+1">
<input type="submit" value="-1">
</form>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
The number of descriptors determins the size of the matrix. With every Descriptor over 15> loading the page takes longer or doesnt work at all. I am using SQLLite.
Question: How can I increase the loadingspeed and make this work at all? Does a change of DB solve the Problem or should i overthink my concept.
Any Help is appreciated.
I'm building a ecommerce site with django.
I'm creating the page where the orders are processed.
I want to make it so that when an item is "delivered" that order will go to the bottom of the list.
views.py
def orders(request, hour):
#changes status of order from submitted to shipped
if request.method == 'POST':
SUBMITTED = 1
PROCESSED = 2
SHIPPED = 3
CANCELLED = 4
order_id = request.POST['order_id']
this_order = Order.objects.get(pk=order_id)
if this_order.status == SUBMITTED or this_order.status == PROCESSED:
this_order.status = SHIPPED
elif this_order.status == SHIPPED:
this_order.status = SUBMITTED
this_order.save()
return HttpResponseRedirect('/orders/' + hour)
#Get all orders from the past 24 hours
tz=pytz.timezone('America/Los_Angeles')
now_nonaware = datetime.datetime.now()
now = timezone.make_aware(now_nonaware,tz)
orders = Order.objects.filter(date__range=[now - datetime.timedelta(hours=20), now]).filter(time=hour)
#get all orders from every college drop
revelle_orders = orders.filter(location = "revelle")
muir_orders = orders.filter(location = "muir")
marshall_orders = orders.filter(location = "marshall")
erc_orders = orders.filter(location = "erc")
warren_orders = orders.filter(location = "warren")
sixth_orders = orders.filter(location = "sixth")
orderlocations = {"revelle": revelle_orders, "muir" : muir_orders, "marshall" : marshall_orders,
"erc": erc_orders, "warren": warren_orders, "sixth": sixth_orders}
orders_dict = {"orderlocations" : orderlocations, "hour": hour}
return render_to_response('orders.html', orders_dict, context_instance=RequestContext(request))
HTML:
Order page for {{hour}}
</br>
</br>
{% for location, orders in orderlocations.items %}
{% if orders %}
{{ location|capfirst }}
<table>
<tr>
<td>#</td>
<td>Name</td>
<td>Email</td>
<td>Order</td>
<td>Delivered</td>
<td>Phone</td>
</tr>
{% for ord in orders %}
{% for food in ord.orderitem_set.all %}
<tr>
{% if forloop.counter == 1 %}
<td>{{forloop.parentloop.counter}}</td>
<td>{{ord.full_name}}</td>
<td>{{ord.email}}</td>
{% else %}
<td colspan="3"></td>
{% endif %}
<td>{{food.name}} (x{{food.quantity}})</td>
{% if forloop.counter == 1 %}
<td>
<form action="" method="POST">
{% csrf_token %}
<input type="hidden" name="order_id" value="{{ ord.pk }}"/>
<input type="hidden" name="action=" value="toggledelivery"/>
<button type="submit">{% ifnotequal 3 ord.status %} Not {% endifnotequal %}Delivered</button>
</form>
</td>
<td>{{ord.phone}}</td>
{% endif %}
</tr>
{% endfor %}
{% endfor %}
</table>
</br>
</br>
{% endif %}
{% endfor %}
This sounds like a job for model ordering meta options on a class.
For example in your model class add a sub-class called Meta:
class MyModel(models.Model):
# model fields here...
class Meta:
ordering = ['status']
You can add a - in front of status to sort in descending order. You can also chain together multiple fields for ordering:
class Meta:
ordering = ['status', '-order_date']
hmm since there's this part
<button type="submit">{% ifnotequal 3 ord.status %} Not {% endifnotequal %}Delivered</button>
maybe something like this in your orders view?
orders = Order.objects.filter(date__range=[now - datetime.timedelta(hours=20), now]).filter(time=hour).extra({"is_completed_order": "status == 3"}).order_by('is_completed_order')
e.g. compute an extra is_completed_order boolean field and order on that
I need some help building a dynamic formset in django. I understand that some javascript is required. I am no javascript expert. But I found some example code and I'm trying to fit it to work on my particular form. When I click the Add button nothing happens. And I'm at a loss on how to move forward. Any suggestions?
Model is for attendee event registration. A customer can register multiple people to attend an event.
Trying to get an add attendee button.
# models.py
class Customer(models.Model):
event = models.ForeignKey(Event)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
address1 = models.CharField(max_length=60)
address2 = models.CharField(max_length=60, blank=True)
city = models.CharField(max_length=30)
state = models.CharField(max_length=2)
zipcode = models.CharField(max_length=5)
class Attendee(models.Model):
event = models.ForeignKey(Event)
sponsor = models.ForeignKey(Customer)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
# forms.py
CustomerFormset = inlineformset_factory(Customer, Attendee, form=AttendeeForm, exclude=('event'), extra=2)
# templates/register.html
<form action="/enroll/register3/{{ event.id }}/" method="post">{% csrf_token %}
<p> Sponsor information: </p>
<table>
{{ customer }}
</table>
<hr>
<p> Students Attending: </p>
{% for attendee in attendees.forms %}
<div class="formgroup">
{{ attendee }}
{% if attendee.nested %}
{% for formset in attendee.nested %}
{{ formset.as_table }}
{% endfor %}
{% endif %}
</div>
{% endfor %}
<div>
Nothing happens when 'add_more' is clicked. ??
<input type="button" value="Add Attendee" id="add_more">
<input type="submit" value="Submit">
</div>
</form>
<script>
$('#add_more').click(function() {
//cloneMore('div.table:last', 'service');
cloneMore('div.table:last', 'formgroup');
});
function cloneMore(selector, type) {
console.log('cloneMore');
var newElement = $(selector).clone(true);
var total = $('#id_' + type + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
});
newElement.find('label').each(function() {
var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
$(this).attr('for', newFor);
});
total++;
$('#id_' + type + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
</script>
It looks like you took javascript from this question, but that you did not adapt your HTML structure.
As I can see in your snippet (which also looks like it will produce highly invalid html, ie. tr in divs):
{% for attendee in attendees.forms %}
<div class="formgroup">
{{ attendee }}
{% if attendee.nested %}
{% for formset in attendee.nested %}
{{ formset.as_table }}
{% endfor %}
{% endif %}
</div>
{% endfor %}
And his:
{{ serviceFormset.management_form }}
{% for form in serviceFormset.forms %}
<div class='table'>
<table class='no_error'>
{{ form.as_table }}
</table>
</div>
{% endfor %}
If you want the same exact javascript piece of code, then you should have the same exact HTML structure. The first thing you're doing in JS is passing div.table:last as selector but you have no div.table in your HTML.
Your best bet is to try to make the javascript yourself. As a webpage developer, javascript will help you a lot.