In my Django project, I save the data in a field that I have made multiple selections to the database using the getlist function and the POST method. Then I pull this data from the database and print it on an html form, but I cannot access the list data properly unless I split it here.
views.py
def record_form(request):
if request.method == "POST" and 'registrationSave' in request.POST:
records = Records()
records.medications = request.POST.getlist('medications')
records.scale_used = request.POST.getlist('scale_used')
records.save()
return redirect('/index/tables')
def editRecords(request,id):
edit_records = Records.objects.get(id=id)
if edit_records.medications is not None:
edit_records.medications = edit_records.medications.split(",")
if edit_records.scale_used is not None:
edit_records.scale_used = edit_records.scale_used.split(",")
institutionName = Institution.objects.all()
medicationName = MedicationName.objects.all()
return render(request,"update_record.html",{"Records": edit_records,
"institutionName":institutionName,"medicationName":medicationName})
update.html
<div class="col-4">
{% for medication in Records.medications%}
<div class="mb-3 col">
<label for="">İlaç Adı:</label>
<select class="form-select" name="medications" id="medications">
<option {% if medication == '{{medicationName.medicationName}}' %} selected {%endif%}>{{medication}}</option>
{% if medicationName%}
<p>{{medicationName}}</p>
{% for medicationName in medicationName %}
<option value="{{medicationName.medicationName}}">{{medicationName.medicationName}}</option>
{%endfor%}
{%endif%}
</select>
</div>
{%endfor%}
</div>
I'm sharing my code pieces above with you, and I'm leaving the screenshot of the update.html page below. How can I follow a method to avoid [ ] and ' ' signs?
enter image description here
Thank you in advance for your help
Related
Context
I am building a simple "todo" flask app with an SQLAchemy database.
The tasks are sorted by sections (check the image below to see how it is organized).
Once I implemented all the functionalities I wanted, I ran into the issue which was the whole page
got refreshed each time I triggered a button (add/edit/delete/update_status).
Then I found out hotwire which is amazing to handle this.
This my taskManager.html organization:
<!--New task button-->
<turbo-frame id="data_frame-add">
<button class="btn-add" onclick="openAddForm()">...</button>
<div class="form-popup" id="myForm">
<form name="AddTaskForm" action="{{ url_for('add_task') }}" class="form-container" method="POST">
<label for="section"><b>Section</b></label>
<input type="text" id="section" name="section" required>
<label for="content"><b>Task</b></label>
<input type="text" id="content" name="content required>
<button type="submit" class="btn">Add</button>
</form>
</div>
</turbo-frame>
<!--Display sections and tasks-->
<div class="flex-row">
{% for section in sections %}
<turbo-frame id="data_frame-{{ section }}">
<div class="flex-column">
<h2>{{ section }}</h2>
{% for task in tasks %}
{% if task.section == section %}
<p>{{ task }}</p>
<button class="satus"></button>
<button class="edit"></button>
<div class="form-popup" id="form-{{ task.id }}">...</div>
<button class="delete"></button>
<div class="form-popup" id="form-{{ task.id }}">...</div>
{% endif %}
{% endfor %}
</div>
</turbo-frame>
{% endfor %}
</div>
Using a turbo frame with id data_frame-{{ section }} (one for each section) allowed to refresh only the concerned section when hitting status, edit and delete buttons (for example, hitting delete button of task 2 of Section 2 will only refresh the turbo frame data_frame-Section 2). However as the New task button is out of theses turbo frames, It works differently and this is a different challenge...
Issue
When adding a new task, I would like the section of the task (entered here <input type="text" id="section" name="section"...>) to be saved in a variable which will be used to target a specific <turbo-frame id="data_frame-{{ section }}"> and refresh it without refreshing the whole page.
At the moment as the New task button is wrapped with <turbo-frame id="data_frame-add"> it is self contained (meaning if I'm adding a task 5 to Section 1 only the turbo frame with id data_frame-add is refreshed not the data_frame-Section 1 so I need to manually refresh the page to see changes)
What I tried
I added data-turbo-frame to the form:
<form name="AddTaskForm" action="{{ url_for('add_task') }}" class="form-container" method="POST" data-turbo-frame="data_frame-Section 1">
in order to be able to refresh the "data_frame-Section 1" when I add a New task in section Section 1, and it works! But I would like to make this data-turbo-frame="data_frame-<section>" with <section> a variable that get the value of <input type="text" id="section" name="section"...>
To achieve this I removed data-turbo-frame="data_frame-Section 1" in the form:
<form name="AddTaskForm" action="{{ url_for('add_task') }}" class="form-container" method="POST">
and added a Javascript part:
var sectionValVar = document.getElementById("section").value;
const sectionValPref = "data_frame-";
let sectionVal = sectionValPref + sectionValVar;
$(".AddTaskForm").attr("data-turbo-frame", sectionVal);
sectionVal is supposed to get the variable value "data_frame-<section>" and last line add "data-turbo-frame" = "data_frame-<section>" to the <form name="AddTaskForm"...>
But this doesn't work. I'm not sure if this even possible to make as it looks tricky...
But if someone has any hint or fix for this It would be amazing !
Thank you !
Other ressources
This is my add_task route in my python flask app:
#app.route('/add', methods=['GET', 'POST'])
def add_task():
content = request.form.get('content')
section = request.form.get('section')
task = Task(content=content, section=section)
db.session.add(task)
db.session.commit()
return redirect(url_for('taskManager'))
This looks like it would work but I don't see an event listener to set the form data-turbo-frame attribute whenever the input value changes.
You need to update the attribute either before the form submits or whenever the input gets updated.
this is how you could do it with jquery
$("#section").change(function() {
let sectionAndPrefix = "data_frame-" + $("#section").val()
$(".AddTaskForm").attr("data-turbo-frame", sectionAndPrefix);
})
in vanilla javascript
const sectionInput = document.querySelector("#section")
sectionInput.addEventListener("input", function() {
const taskForm = document.querySelector(".AddTaskForm")
const sectionAndPrefix = "data_frame-" + sectionInput.value
taskForm.setAttribute("data-turbo-frame", sectionAndPrefix)
})
html file
<div id="calculator">
<h2>Kalkuleeri saematerjali hind</h2>
<form method="post" action="{% url 'products' %}">
{% csrf_token %}
<label>Valige materjali kvaliteet/tüüp:</label><br>
<select name="tyyp">
<option value="taiskant">Täiskant</option>
<option value="v_poomkant">Väike Poomkant</option>
<option value="s_poomkant">Suur Poomkant</option>
<option value="voodrilaud">Voodrilaud</option>
</select><br><br>
{% if not tyyp %}
<button type="submit">Edasi</button><br><br>
{% endif %}
</form>
<form method="post" action="{% url 'products' %}">
{% csrf_token %}
{% if tyyp %}
<label>Valige mõõdud: (Paksus mm x Laius mm)</label><br>
<select name="moot">
{% for product in products %}
<option value="1">{{ product.nimi }}</option>
{% endfor %}
</select><br><br>
<label>Pikkus:</label><br>
<select name="pikkus">
<option value="kunikolm">Kuni 3,1 m</option>
<option value="kolmkuniviis">3,2 - 5,1 m</option>
<option value="viiskunikuus">5,2 - 6,0 m</option>
</select><br><br>
<label>Kogus:</label><br>
<input type="number" required>
<select name="yhik">
<option value="tm">Tihumeetrit</option>
<option value="jm">Meetrit</option>
<option value="lauda">Lauda</option>
</select><br><br>
<button type="submit">Kalkuleeri</button>
<input type="text" class="calculator-screen" value="" disabled />
{% endif %}
</form>
views.py file
def products_view(request, *args, **kwargs):
taiskant_list = Taiskant.objects.all()
s_poomkant_list = S_Poomkant.objects.all()
v_poomkant_list = V_Poomkant.objects.all()
voodrilaud_list = Voodrilaud.objects.all()
context = {}
if request.method == "POST":
tyyp = request.POST['tyyp']
context['tyyp'] = tyyp
if request.POST['tyyp']=="taiskant":
context['products'] = taiskant_list
return render(request, "products.html", context)
elif request.POST['tyyp']=="s_poomkant":
context['products'] = s_poomkant_list
return render(request, "products.html", context)
elif request.POST['tyyp']=="v_poomkant":
context['products'] = v_poomkant_list
return render(request, "products.html", context)
elif request.POST['tyyp']=="voodrilaud":
context['products'] = voodrilaud_list
return render(request, "products.html", context)
else:
return render(request, "products.html", context)
The problem is, I am trying to create a live form(after choosing first select form option, it automatically renders second select form options without pressing a button).
It should be calculator, but without "Calculate button". It has to update/fill rest of the forms depending on first form choice. And after filling 4 fields, it calculates the "price".
Should I use Django-Forms or html/js for this?
Feel free to ask any questions if I didnt express myself understandably.
Since this is for homework, I'll point you in the right direction.
Let's say we have Make and Model of cars (a common example). There are a number of ways to create a dynamic form and store the data. You could use a dict or you could store the items in the db.
You would need a function that your front-end could call:
from django.http import JsonResponse
def get_models(request, make):
# query the db, or get the results from a global / readonly dict?
data = global_model_dict[make]
# return json for the js caller
return JsonResponse(data, content_type="application/json")
Add an entry in "urls" for it.
urlpatterns = [
# whatever else you have in here
path('models/<str:make>', views.get_models)
]
Finally, you'd need some javascript to call it. JQuery would be simple to include and would help this a lot. Something like this:
var settings = {
"url": "/myapp/models/honda",
"method": "GET",
"timeout": 0,
};
$.ajax(settings).done(function (response) {
console.log(response);
});
From there, you'll have the data you need to append / set html on the page. You'll do that with a loop where I have "console.log" right now.
Some sources for you to read.
https://docs.djangoproject.com/en/3.1/topics/http/urls/
https://api.jquery.com/
I'm making a workout calendar website where a user can add workouts with varying amounts of lift, sets and reps, etc. Thus, I need a form that adds a field when a user clicks a button. I've made a template and some javascript to describe what it is I want to achieve exactly:
url:
url(r'^add/(?P<year>[0-9]+)/(?P<month>[0-9]+)/(?P<day>[0-9]+)/$', views.add_workout, name = 'add_workout')
template:
{% block hidden %}
{% include "workoutcal/liftrow.html" %} {# To be used by Javascript #}
{% include "workoutcal/cardiorow.html" %}
{% endblock %}
<form action="{% url 'add_workout' date.year date.month date.day %}" method="post">
<div class="row">
<div class="col-xs-2">
<p id="date">{{ date.year }}-{{ date.month }}-{{ date.day }}</p>
<input type="hidden" name="date" value="{{ date }}">
</div>
</div>
<h2 class="col-xs-12">Lifts</h2>
<div id="liftrows">
{% for i in range %}
{% include "workoutcal/liftrow.html" %}
{% endblock %}
</div>
<div class="row">
<div class="col-xs-0"></div>
<label class="col-xs-2"><button type="button" id="addliftbutton">One more lift</button></label>
</div>
<h2 class="col-xs-12">Cardio</h2>
<div id="cardiorows">
{% include "workoutcal/cardiorow.html" %}
</div>
<div class="row">
<label class="col-xs-2"><button type="button" id="addcardiobutton">One more cardio</button></label>
</div>
<div class="row">
<div class="col-xs-10"></div>
<label class="col-xs-2"><input type="submit" id="submitbutton" value="Save Workout"></label>
</div>
</form>
javascript:
//Adding onclick to buttons
document.getElementById('addliftbutton').onclick = addLiftRow;
document.getElementById('addcardiobutton').onclick = addCardioRow;
for (var i=0; i<setsBoxes.length; i++){
setsBox = setsBoxes[i];
setsBox.onchange = insertRepFields;
}
function addLiftRow(){
var liftRowElements = document.getElementById('liftrows');
var hidden_liftrow = document.getElementById('hidden').getElementsByClassName('lift')[0];
var new_liftrow = hidden_liftrow.cloneNode(true);
liftRowElements.appendChild(new_liftrow);
}
function addCardioRow(){
var cardiorows = document.getElementById('cardiorows');
var hidden_cardiorow = document.getElementById('hidden').getElementsByClassName('cardio')[0];
var new_cardiorow = hidden_cardiorow.cloneNode(true);
cardiorows.appendChild(new_cardiorow);
}
function insertRepFields(){} // big function that inserts as many input fields as the number inside the box whose event called the function.
2 questions:
1. Is there a better way to do this in Django?
2. If this is the best way, how do I go about sending the data of my massive form back to django? Since I don't know exactly how many fields there will be, I don't know how to create a form that accepts a variable amount of fields, and fields within fields.
Here's how a filled-in form could look:
The best way to accomplish that is inserting inputs with the same name and then in Django get all those inputs as a list like:
def view(request):
inputs = request.POST.getlist('your_input_name')
for i in inputs:
Model.objects.create() # Save your model
I have a two pronged question and would appreciate any advice.
1) I have a flask template with multiple forms in it. Each form presents the user with a list that is dynamically generated from a mongodb query.
name_list = [p['name'] for p in posts.find({'type': "server"})]
name_list.insert(0, "select")
This is then refernced in my html template (thank you again to the person who helped me with this loop on a previous question)
<select name="option" id="myselect" onchange="this.form.submit()">
{% for x in server_list %}
<option value="{{ x }}"{% if loop.first %} SELECTED{% endif %}>{{ x }}</option>
{% endfor %}
This selection is then passed back to python to be used in another db query and then present the user with another dropdown select box. However when the first form is submitted, the new page render means that that value is now lost on the html and appears blank. Is there a way to keep this choice persistent so when after the new page render it still appears?
2) Secondly, I would like to keep a running list of what options the user makes, however given the if, elif structure I'm using that variable looses state and can no longer used. Eventually I would like to present the user with two sets of these dropdown menus to generate to final db querys that I can compare and return the difference, however I can only do this if I can keep state of these values generated in the loops.
Please see full code below:
python:
from flask import render_template
from flask import request
from flask import Response
from app import app
from pymongo import MongoClient
#app.route('/', methods=['POST','GET'])
#app.route('/index', methods=['POST','GET'])
def index():
user = {'name': 'Bob'}
client = MongoClient('mongodb://localhost:27017/')
db = client['test-database']
collection = db.test_collection
name_list = []
posts = db.posts
name_list = [p['name'] for p in posts.find({'type': "server"})]
name_list.insert(0, "select")
select_list = []
#if request.form['submit'] == 'myselect':
if request.method == 'POST' and request.form.get('option'):
choice = request.form.get('option')
select_list.append(choice)
sub_name_list = [q['type'] for q in posts.find({'name': choice})]
return render_template("index.html",
sub_server_list=sub_name_list)
elif request.method == 'POST' and request.form.get('option1'):
choice1 = request.form.get('option1')
select_list.append(choice1)
return render_template("index.html",
title='Database selector',
user='Person',
choiced=choice1,
total_choice=select_list)
return render_template("index.html",
title='Database selector',
user='Person',
server_list=name_list)
html/jinja:
<html>
<head>
<title>{{ title }} - Test</title>
</head>
<body>
<h1>Hi, {{ user }}!</h1>
<h2>Database selector</h2>
<h3><table><form action="" method="post">
<td>
<label>Select1 :</label>
<!--<select name="option" width="300px">-->
<select name="option" id="myselect" onchange="this.form.submit()">
{% for x in server_list %}
<option value="{{ x }}"{% if loop.first %} SELECTED{% endif %}>{{ x }}</option>
{% endfor %}
</select>
</td>
</form></table></h3>
<h3><table><form action="" method="post">
<td>
<label>Select2 :</label>
<select name="option1" id="sub_myselect" onchange="this.form.submit()">
{% for y in sub_server_list %}
<option value="{{ y }}"{% if loop.first %} SELECTED{% endif %}>{{ y }}</option>
{% endfor %}
</td>
</form></table></h3>
<h3>Here is the choice: {{ choiced }}</h3>
<h3>Here is the choice: {{ total_choice }}</h3>
</body>
</html>
Any pointers or ideas would be greatly appreciated.
Have a look at sessions. You might have to change the way you store your data though, maybe by finding an appropriate name for choiceand choice1 and storing them in a dict.
This question already has answers here:
django MultiValueDictKeyError error, how do I deal with it
(9 answers)
Closed 8 years ago.
After trawling the internet for hours trying to no avail, I've come here in hope that maybe somebody can steer me in the correct direction.
So I'm new to django and stuck trying to use ajax in a template to pass data to a view. I have drop down menus that are populated from a database and when the user selects the type of result and model, I'm just trying to get it to pass these values to the view method. The reason why I'm doing this is because the view page populates the template (using extends), by generating an html page via a perl script that accepts these variables (result, model).
view.py
def platform_pass_rate(request):
#some other stuff
#This is currently always true
if request.method == 'GET':
#It is an issue however, because this never gets anything, just as request.GET.items() returns nothing
resultVar = request.GET['resultValue']
# modelVar = request.POST['selectedModelValue']
subprocess.call(["perl", "static/static/perl/passRateByPlatform.pl", resultVar, "Ahmed_00"])
#This calls the perl script. Currently set up so that just a default result is entered - so I now GET is working
else:
subprocess.call(["perl", "static/static/perl/passRateByPlatform.pl", "liftforce", "Ahmed_25"])
#Default html page created by script when user does not select anything
current_url = get_full_path(request)
return render_to_response("data_form_platform.html", {'our_url': current_url, 'study_models': study_models,'study_results': study_results})
urls.py
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('AppFalconV1.views',
# Examples:
url(r'^$', 'home'),
url(r'^Pass_Rate_by_Build/$', 'build_pass_rate'),
url(r'^Pass_Rate_by_Platform/$', 'platform_pass_rate'),
url(r'^Platform_Coverage/$', 'platform_coverage'),
url(r'^Regression_Coverage/$', 'regression_coverage'),
url(r'^Coverage_All_Builds/$', 'coverage_all_builds'),
# url(r'^test/$', 'get_current_url'),
url(r'^time/$', 'current_datetime'),
#url(r'^time/plus/(\d{1,2})/$', 'hours_ahead'),
url(r'^admin/', include(admin.site.urls)),
)
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
Revised script in base.html
<script type="text/javascript">
$(document).ready(function () {
{# $.ajaxSetup({ cache: false });#}
var current_url = $('#current_url').text();
var id = current_url.trim();
$('#' + id).addClass('active');
$('#platform_data_form_button').click(function () {
var selectedResultValue = $('#platform_type_of_result :selected').text();
console.log(selectedResultValue);
var selectedModelValue = $('#platform_models :selected').text();
console.log(selectedModelValue);
$('#platform_type_of_result').change(function () {
var selectedResultValue = $('#platform_type_of_result :selected').text();
console.log(selectedResultValue);
});
$('#platform_models').change(function () {
var selectedModelValue = $('#platform_models :selected').text();
console.log(selectedModelValue);
});
$.get("/Pass_Rate_by_Platform/", { resultValue: selectedResultValue, modelValue: selectedModelValue}, function (response) {
console.log("workinggggggg");
//alert(response);
});
});
});
</script>
Location of dropdown buttons - data_form_platform.html
{% extends 'platform_pass_rate.html' %}
{% block data_form_platform_content %}
<form class="form-horizontal">
<fieldset>
<div class="form-group">
<label class="col-md-2 control-label" for="type_of_result">Type of result</label>
<div class="col-md-3">
<select id="platform_type_of_result" name="type_of_result" class="form-control">
{% for result in study_results %}
{% if result != "testid" and result != "studyid"%}
<option value="{{ result }}">{{ result }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="model">Model</label>
<div class="col-md-3">
<select id="platform_models" name="model" class="form-control">
{% for model in study_models %}
<option value="{{ model }}">{{ model }}</option>
{% endfor %}
</select>
</div>
<label class=" control-label" for="model"></label>
<div class="col-md-1" style="margin-left: -20px" id="platform_data_form_button">
<a href="" class="btn btn-primary btn-success" ></span> Confirm</a>
</div>
</div>
</fieldset>
</form>
{% endblock %}
This just seems to be a problem with your Javascript. You're getting the value for selectedResultValue when the page is first loaded, presumably when no value is selected. The Ajax request is made when the button is clicked, but you don't fetch the new value inside that click function: so you still use the old, empty value. Just move that line inside the function.