views.py
def what(request):
user = request.user
report = Report.objects.get(user=user.id)
reportnotesform=ReportNotes(instance=report)
reportform = ReportForm(instance=report)
typeList = Types.objects.filter(user=user, is_active=True,parent_type_id=None)
list = []
for type in typeList:
if not type.parent_type_id:
list.append(type)
subtype = Types.objects.filter(parent_type_id=type.id, is_active=True)
for subtypes in subtype:
list.append(subtypes)
if request.method == 'POST':
ReportType.objects.filter(report=report).delete()
checked_ones = [unicode(x) for x in subtype if unicode(x) in request.POST.keys()]
reportnotesform=ReportNotes(request.POST,instance=report)
if reportnotesform.is_valid():
report=reportnotesform.save(commit=False)
report.user=request.user
report.save()
for entry in checked_ones:
r = ReportType()
r.report = report
r.title = entry
r.save()
return redirect('/member/where/')
checked_ones = [x.title for x in ReportType.objects.filter(report=report)]
return render(request, 'incident/what.html',
{
'newreport_menu': True,
'typeList':list,
'checked_ones':checked_ones,
# 'typelist': typelist,
'ReportNotes':reportnotesform,
'ReportForm':reportform
})
models.py
class ReportType(models.Model):
report = models.ForeignKey(Report)
title = models.CharField('Incident Type', max_length=200)
template
{% for type in typeList%}
{% if type.parent_type_id == None %}
<h1>{{type.title}}</h1>
{% else %}
<p><input type="checkbox">{{type.title}}</input></p>
{% endif %}
{% endfor %}
I am using model form to display the check box,dynamically.
This is my view where i am taking the values from database and displaying.The values filtered by typelist object requires to display values along with check box.For types object,doesn't matter.Is any way to do it in django.
This should work for you:
<h1> {% for type in types %}{{type.title}}<br />{% endfor %}</h1>
<form action="" method="post">
{% for field in typelist %}
{% if field.title in checked_ones %}
<label><input type="checkbox" checked="true" name="{{field}}">{{ field }}</label><br />
{% else %}
<label><input type="checkbox" name="{{field}}">{{ field }}</label><br />
{%endif%}
{% endfor %}
</form>
def what(request):
user = request.user
types = Types.objects.filter(user=user.id, parent_type_id=None).order_by('title')
typelist=Types.objects.filter(user=user.id,parent_type_id__isnull=False).order_by('title')
reporttypeForm = ReportTypeForm()
if request.method == 'POST':
ReportType.objects.filter(report=#your report).delete()
checked_ones = [unicode(x) for x in typelists if unicode(x) in request.POST.keys()]
for entry in checked_ones:
r = ReportType()
r.report = # the hardcoded report
r.title = entry
r.save()
...
reporttypeForm = ReportTypeForm(request.POST)
if reporttypeForm.is_valid():
reporttypeForm.save()
checked_ones = [x.title for x in ReportType.objects.filter(report=#your report)]
return render(request, 'incident/what.html',
{
'checked_ones':checked_ones,
'newreport_menu': True,
'types':types,
'typelist': typelist,
'reporttypeForm':ReportTypeForm
})
Good luck!
Without knowing anything about why you're trying to do it this way, it looks like you're overcomplicating your problem by trying to make it dynamic, when you could just use a models.BooleanField(), which Django will automatically display as a checkbox. It'd be simpler, and make the code easier to read too.
Related
I am not able to access my inputs thorugh request.POST.getlist() method, and when I run my program, all other fields are okay and I can see the result but when it comes to choices it return empty list.
views.py
if request.method == 'POST':
teacher_get = request.POST.get('teacher')
department_get = request.POST.get('department')
subject_get = request.POST.get('subject')
answer_list = []
print(teacher_get)
print(department_get)
print(subject_get)
answer = request.POST.getlist("question_{{question.id}}")
print(answer)
OUTPUT:
Ahmad
Software Engineering
Programming
[]
[26/Nov/2020 15:48:12] "POST / HTTP/1.1" 200 2353
INDEX.HTML
<form action="{% url 'index'%}" method="POST">
{% csrf_token %}
<select name="teacher">
{% for question in question %}
<ol>{{ question.question }}</ol>
{% for choice in rating_choices %}
<input type="radio" name="question_{{question.id}}" value="{{choice.0}}">{{choice.1}}
{% endfor %}
{% endfor %} <br>
<input type="submit" value="Vote">
The request will not contain any values for the question_{{question.id}} name, since the template is rendered. This means that at the side of the client, it will look for a Question with .id equal to 25 as name="question_25".
You thus will need to reconstruct the Questions, and read these individually, for example something like:
if request.method == 'POST':
teacher_get = request.POST.get('teacher')
department_get = request.POST.get('department')
subject_get = request.POST.get('subject')
answer_list = []
print(teacher_get)
print(department_get)
print(subject_get)
for question in Question.objects.all():
answer = request.POST.get(f'question_{question.pk}')
print(answer)
or you can look for all the keys that start with question_, and thus retrieve the values for all picked choices of the question_… keys:
if request.method == 'POST':
teacher_get = request.POST.get('teacher')
department_get = request.POST.get('department')
subject_get = request.POST.get('subject')
answer_list = []
print(teacher_get)
print(department_get)
print(subject_get)
answers = [v for q, v in request.POST.items() if q.startswith('question_')]
[** found a fix, see below **]
I'm having trouble getting Django 2 Paginator to work with a modelformset. There are three models, Place & Hit (one-to-many), and Link. The 'validator' view pages through Place objects 1 at a time, builds a queryset of Hits filtered by the FK placeid. The context sent to the template includes 1) the formset=HitFormSet, 2) a 'records' list with only the one Place object, and 3) the Paginator page.
The template renders the single Place record on the left side, and a scrolling list of Hit forms on the right. The Hit form has two added fields, 'match' (3 radio buttons) and 'flag' (checkbox). The user selects those if one or more Hits match the Place. Upon submitting, a new Link record is created with a placeid, a hitid, and values from the radios and checkbox. Also, a 'reviewed' field in the Place record is set to True.
The code below works to load Place #1, then page through the records - displaying a Place and its Hits. Clicking the Save button creates a new Link record as desired. The problem is that after the save, although the next Page loads on the left, its corresponding hits don't. By displaying pprint(locals()) I can see the correct hits are in the queryset, but the Hit fields in the formset all retain the values from the previous set of forms. The Paginator is advancing and the next Place loads, but not its Hit formset.
I've banged at this for a couple days, read docs, searched, etc. Any ideas?
view.py
def validator(request):
record_list = Place.objects.order_by('placeid').filter(reviewed=False)
paginator = Paginator(record_list, 1)
page = request.GET.get('page')
records = paginator.get_page(page)
count = len(record_list)
context = {
'records': records,
'page': page if request.method == 'GET' else str(int(page)-1)
}
placeid = records[0].placeid
hitid = records[0].hitid
q = Hit.objects.filter(placeid=placeid)
HitFormset = modelformset_factory(
Hit, fields = ['id','hitid', ],form=HitModelForm,extra=0)
formset = HitFormset(request.POST or None, queryset=q)
context['formset'] = formset
if request.method == 'GET':
method = request.method
print('a GET')
else:
if formset.is_valid():
print('formset is valid')
for x in range(len(formset)):
link = Link.objects.create(
placeid = placeid,
hitid = formset[x].cleaned_data['hitid'],
match = formset[x].cleaned_data['match'],
flag = formset[x].cleaned_data['flag'],
)
# flag Place record as reviewed
matchee = get_object_or_404(Place, placeid = placeid)
matchee.reviewed = True
matchee.save()
else:
print('formset is NOT valid')
print(formset.errors)
pprint(locals())
return render(request, 'validator/template.html', context=context)
template.html
{% block content %}
<div class="pagination">
<span class="step-links">
... all standard, works fine
</span>
</div>
{% for record in records %}
{% if records.has_next %}
<!-- <form id="form_related" method="POST" action="" > -->
<form id="form_related" method="POST" action="?page={{ records.next_page_number }}" >
{% else %}
<form id="form_related" method="POST" action="" >
{% endif %}
{% csrf_token %}
{{ formset.management_form }}
<input type="hidden" name="placeid" value="{{ record.placeid }}" />
{% for form in formset %}
<div class="row">
<div class="col-sm-4 id="place-record">
<!-- Place attributes -->
</div>
<div class="col-sm-8" id="hit-forms">
<div id="review">
<span>{{ form.match }} flag: {{ form.flag_geom }}</span>
</div>
<div id="hit">
<!-- Hit attributes -->
</div>
</div>
</div>
{% endfor %}
{% endfor %}
{% endblock%}
The answer (or an answer) turned out to be doing a redirect immediately after the save/POST. The save of Link record removes the Place from the queue, so the page is always "1"
view.py
...
if formset.is_valid():
for x in range(len(formset)):
link = Link.objects.create(
placeid = placeid,
tgnid = formset[x].cleaned_data['tgnid'],
match = formset[x].cleaned_data['match'],
flag_geom = formset[x].cleaned_data['flag_geom'],
)
matchee = get_object_or_404(Place, placeid = placeid)
matchee.reviewed = True
matchee.save()
return redirect('/formset/?page='+page)
else:
print('formset is NOT valid')
print(formset.errors)
...
I have created a form and I POST selection with an action to go to specific url. Although, once directed the template does not update.
I need to hit Enter again and then obviously my request is lost so I get exception value get_context_data() takes exactly 2 arguments (1 given)
any ideas why ?
Below is my code and print screen of the problem.
url
url(r'^all_rooms/$', views.AllRoomsView.as_view(), name='roomsdetails'),
template
<form action="/blocks/all_rooms/" method="post" >
{% csrf_token %}
<ul>
{% for choice in form.my_choice_field.field.choices %}
<li>
<input type="radio" name="my_choice_field" value="{{choice.0}}"
{% ifequal form.my_choice_field.data choice.0 %}
checked="checked"
{% endifequal %}/>
<label for="">{{choice.1}}</label>
</li>
{% endfor %}
</ul>
<input type="submit" value="Submit" />
</form>
EDIT:
Below is my AllRoomsView class. I suspect this is the class where the problem is.
class AllRoomsView(ListView):
template_name = 'prostats/roomsdetail.html'
queryset = Room.objects.all()
def get_context_data(self, request, **kwargs):
context = super(AllRoomsView, self).get_context_data(**kwargs)
context['rooms'] = Room.objects.all()
context['rlog'] = RoomLog.objects.all()
roomsdates = []
for r in context['rlog']:
if r not in roomsdates:
roomsdates.append(r.update_date)
roomextracted = []
for i in roomsdates:
if i not in roomextracted:
roomextracted.append(i)
context['roomextracted'] = roomextracted
choosend = '2016-02-16'
context['roomfiltersettime'] = RoomLog.objects.filter(update_date__lte = choosend)
return context
I have a model with a lot of fields. I only have a few fields I that I want to be required. So instead of the change list super long, I want to have a short change list then have admin actions that can give predefined subsets of the fields.
The initial action takes me to the correct page but when I submit the form it returns me to whatever page I designate, but doesn't update the fields. I am okay with tearing this down starting over again if needed. I think what I really need to know, what do I put in the action="" portion of the html to have the recursion work properly?
I am using django 1.7. I have to obfuscate a lot of my fields as a cya thing since I am working in a heavily information secure field.
Here is my admin.py
class CredentialAdmin(admin.ModelAdmin):
fields = ['reservedBy','reserveto']
list_display = ['reservedBy','reserveto']
class reserveToFormAdmin(forms.Form):
reservedBy = forms.CharField(widget=forms.Textarea, max_length=50)
reserveto = forms.DateTimeField(widget=forms.DateTimeInput)
def reserveCred(self, request, queryset):
form = None
plural = ''
if 'submit' in request.POST:
form = self.reserveToFormAdmin(request.POST)
for f in form.fields:
print f
print form.is_valid()
print form.errors
if form.is_valid():
reservetos = form.cleaned_data['reserveto']
reservedBys = form.cleaned_data['reservedBy']
print "hello"
count = 0
for cred in queryset:
cred.reserveto = reservetos
cred.reservedBy = reservedByss
cred.save()
count += 1
if count != 1:
plural = 's'
self.message_user(request, "Successfully reserved %s cred%s." % (count, plural))
return HttpResponseRedirect(request.get_full_path(),c)
if not form:
form = self.reserveToFormAdmin(initial={'_selected_action' : request.POST.getlist(admin.ACTION_CHECKBOX_NAME)})
return render(request,'admin/reserveCreds.html',{'creds':queryset, 'form':form, 'path':request.get_full_path()})
reserveCred.short_description = "Reserve Selected Creds"
actions = [check_out_a_cred,check_in_a_cred,audit_creds,CompareAudits,reserveCred]
reserveCreds.html
{% extends "admin/base_site.html" %}
{% block content %}
<p>How long and which department to reserver creds:</p>
<form action="{{ path }}" method="post">{% csrf_token %}
{{ form }}
<input type="submit" name="submit" value="submit" />
<input type="button" value = "Cancel" />
</form>
<h2> reserving: </h2>
<ul>
{% for cred in creds %}
<li> {{ cred.userid }} </li>
{% endfor %}
</ul>
{% endblock %}
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.