There is a list generated in HTML, that represents all objects (Cards).
There is already a delete button, but it's using Django functionality, and it requires a page to reload to take effect.
Is there a simple way to include AJAX into the program?
I am a beginner to JavaScript and AJAX. I have tried some copy-paste solutions. I even tried to deconstruct a simple Django Ajax CRUD app, but it has too many functionalities, and it seemed like an overkill for my app (i would have to rewrite all the views, templates and urls).
So I decided to ask a question over here with my own code.
views.py (List objects view)
def all_cards(request):
cards = Card.objects.all()
return render(request, 'all_cards.html', {'cards':cards})
all_cards.html
<body>
{% if cards %}
<table class="table" id="card-table">
<tr>
<th>Card owner name</th>
<th>Card balance</th>
</tr>
{% for card in cards %}
<tr>
<td>{{ card.cardholders_name }}</td>
<td>{{ card.card_balance }}€</td>
<td><form action="{% url 'card_delete' card.id %}" method="post">
{% csrf_token %}
<input type="submit" value='Delete'>
</form></td>
</tr>
{% endfor %}
{% else %}
<p>There are no cards registered.</p>
{% endif %}
</table>
</body>
urls.py
url(r'(?P<id>\d+)/$', views.card_delete, name='card_delete'),
views.py (Delete object view)
def card_delete(request, id):
card_that_is_ready_to_be_deleted = get_object_or_404(Card, id=id)
if request.method == 'POST':
card_that_is_ready_to_be_deleted.delete()
return HttpResponseRedirect('/all_cards')
As you can see, the form's input(
<input type="submit" value='Delete'>
)calls Django's view via URL.
I expect the delete button to call an AJAX functionality, that will do a similar thing.
How should I go about writing that functionality?
P.S.: This is my first StackOVerflow question, I'm open for constructive criticism.
You should add id to your form and table row first
<form action="{% url 'card_delete' card.id %}" method="post" id="delete_form_{{ card.id }}">
.
<tr id="card_{{card.id}}">
And change button code to:
<input type="button" onclick="submit_delete({{ card.id }})" value="delete">
And use this function to send AJAX request:
<script>
function submit_delete(id) {
$.ajax({
type: $('#delete_form_'+id).attr('method'),
url: $('#delete_form_'+id).attr('action'),
data: $('#delete_form_'+id).serialize(),
success: function (data) {
$('#card'+id).remove()
}
});
}
</script>
Related
I have a problem with trying to get a response from my HTML page using Django (admin).
I have a pretty simple div = contenteditable and need to pass data from this div back after the submit button was clicked.
Everything, including choosing selection and opening the intermediate page works fine. But when I tapped submit button, the condition if "apply" in request.POST failed to work.
Please, tell me, what I'm doing wrong?
This is my Django admin:
class QuestionAdmin(AnnotatesDisplayAdminMixin, admin.ModelAdmin):
def matched_skills(self, question):
return ', '.join(s.name for s in question.skills.all())
def update_skills(self, request, queryset):
if 'apply' in request.POST:
print("something")
skills = []
for question in queryset:
skills.append(self.matched_skills(question))
return render(request,
'admin/order_intermediate.html',
context={'skills': skills})
update_skills.short_description = "Update skills"
This is my order_intermediate.html page:
{% extends "admin/base_site.html" %}
{% block content %}
<form method="post">
{% csrf_token %}
<h1>Adjust skills. </h1>
{% for skill in skills %}
<div>
<div id="title" style="margin-left: 5px" contenteditable="true" > {{ skill }} </div>
</div>
{% endfor %}
<input type="hidden" name="action" value="update_status" />
<input type="submit" name="apply" value="Update skills"/>
</form>
{% endblock %}
Actually, request.POST is an HttpRequest object. For getting available keys in the body of the request, you need to use "request.POST.keys()" method. So, you can simply change your condition to:
if 'apply' in request.POST.keys():
print("something")
In my knowledge, you can not send div content with form submit. However you can use input tag with array in name attribute for this. This will send an array as post variable when submit
First, send skills as a enumerate object from your views
return render(request, 'admin/order_intermediate.html', context={'skills': enumerate(skills)})
Then edit your html to this (Note: if you have css in title id, change it to title class)
{% for i,skill in skills %}
<div>
<input class="title" name="skill[{{ i }}]" value="{{ skill }}" style="margin-left: 5px">
</div>
{% endfor %}
and handle array with any action you want to perform in update_skills()
for skill in request.POST.getlist('skill[]'):
# your code
I have a FieldList form that allows users to enter in an origin and destination for routes they have travelled.
I am trying to add Google's autocomplete API to make it easier for users to enter in addresses into the fields.
forms.py
from flask_wtf import Form
from wtforms import (
StringField,
FormField,
FieldList
)
from wtforms.validators import (
Length,
Optional
)
class RouteForm(Form):
origin = StringField([Optional(), Length(1, 256)])
destination = StringField([Optional(), Length(1, 256)])
class JourneysForm(Form):
ids = []
journeys = FieldList(FormField(RouteForm))
edit.html
{% import 'macros/form.html' as f with context %}
<tbody>
<tr>
{% for journey, route in zip(form.journeys, routes) %}
<td>
{% call f.location_search(journey.origin,
css_class='sm-margin-bottom hide-label') %}
{% endcall %}
</td>
</tr>
{% endfor %}
</tbody>
<div class="col-md-6">
<button type="submit" class="btn btn-primary btn-block">
'Save'
</button>
</div>
macros/forms.html
<head>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&key=<KEY>&callback=initMap" async defer></script>
<script>
function initMap() {
var input = document.getElementById('searchInput');
var autocomplete = new google.maps.places.Autocomplete(input);
}
</script>
</head>
{# Render a form for searching a location. #}
{%- macro location_search(form, css_class='') -%}
<input type="text" class="form-control"
id="searchInput" placeholder="Enter location">
{{ form(class=css_class, **kwargs) }}
{{ caller () }}
{%- endmacro -%}
routes.py
#route('/edit', methods=['GET', 'POST'])
def routes_edit():
routes = get_routes()
journeys_form = JourneysForm()
if journeys_form.validate_on_submit():
for i, entry in enumerate(journeys_form.journeys.entries):
origin = entry.data['origin']
However, this renders two fields. One which contains the Google autocomplete input, but does not submit the value (top). And another field which does not have the Google autocomplete input but submits the value to the db via routes.py (bottom).
Is it possible to combine this into a single field that both contains the Google autocomplete and submits the input value to the db?
WTForms actually renders an input class itself:
<input class="form-control" id="journeys-0-origin" name="journeys-0-origin" type="text" value="" placeholder="Enter a location" autocomplete="off">
Therefore I was unnecessarily duplicating the input element. In order to get Google autocomplete to work I simply just had to pass the input id into my js function:
function initMap() {
var input = document.getElementById('journeys-0-origin');
var autocomplete = new google.maps.places.Autocomplete(input);
}
i want to concatenate a variable in a form action. for example:
<form action="{% url 'addAlumn' ${id} %}" method="POST">
im sure im wrong but i dont have idea how to do this.
this is my function:
<script>
function alumno(obj, obj2, obj3, obj4) {
id = obj;
var no_certificado = obj2;
var nom = obj3;
var curp = obj4;
$("#nombre").val(nom);
$("#cert").val(no_certificado);
$("#curp").val(curp);
}
</script>
Change the form url, remove the ID from urls.py and get the object with the post request. Something like this:
Form
<form action="{% url 'editarAlumno' %}" method="POST">
urls.py
path('NuevaSolicitud/editarAlumno/', login_required(views.EditarAlumno), name='editarAlumno'),
views.py
def EditarAlumno(request):
id = request.POST["id"]
alumno = Alumnos.objects.get(pk=id)
...
...
...
# Make sure you save your object before redirecting
alumno.save()
return redirect('Alumnos')
From what I can see your form action should be '=' to not ':' I'm not sure what the function is used for, looks like you are adding values to the form.
You also need to remove $ from 'id'
Abit more info on what you are trying to do can make it easier to give more help
<form action="{% url 'addAlumn' id %}" method="POST">
this is my table:
<tbody>
{% if lista_alumnos %}
{% for alumno in lista_alumnos %}
<tr>
<td>{{ alumno.no_certificado }}</td>
<td>{{ alumno.nombre_alumno }}</td>
<td>{{ alumno.CURP }}</td>
<td>
<i class="material-icons" data-toggle="tooltip" title="Edit"></i>
<i class="material-icons" data-toggle="tooltip" title="Delete"></i>
</td>
</tr>
{% endfor %}
I've made the sudoku generator and the templates, but now I stuck in posting the whole array(9x9) to Django (i.e. sudoku_checker) for checking the duplicates and determine whether the user can go next game.
Here is my template looks like in Django, and you'll see I've indexed/positioned every single table cell, thought it might help with later checking:
<table>
<caption>Sudoku of the day</caption>
{% for row in numbers %}
<tr>
{% for col in row %}
{% if col is 0 %}
<td>
<input class="d0" size="1" autocomplete="off" maxlength="1" name="{{ forloop.parentloop.counter0 }}{{ forloop.counter0 }}">
</td>
{% else %}
<td id="{{ forloop.parentloop.counter0 }}{{ forloop.counter0 }}">{{ col }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
<button class="btn btn-primary" type="submit">Submit</button>
but then what should I do next? Am I correct to use Form method to Post the data to Django? But how can i make sure all the data have been bundled up when passing through for checking, in terms of both the known numbers and unknown numbers(input by users)? any hints please?
This is the code of the views, but i only completed the numbers_fill_table one, i dont know what to write in second part of views and forms properly to post the exact data i want. Please help!
from .sudoku_generator import sudoku_generator
def board_fill(request):
context = {'numbers': sudoku_generator.final_board()}
template = 'sudoku_board.html'
return render(request, template, context)
When you have the view (you must map it to the url that is used as the form target) it gets the request object. From there you can read the user input:
request.POST.get('44', 0) # Will return 0 if 44 is not found
More hint about writing a view: https://docs.djangoproject.com/en/2.1/topics/http/views/ and mapping the view to the url: https://docs.djangoproject.com/en/2.1/topics/http/urls/
I'm basically trying to develope a Sudoku Solver in Django, and in template I have created a table of 9X9 having the empty cells initially. I want the users to edit those cells and generate a puzzle and submit.
And I want to read that puzzle on POST method but just couldn't do it after searching a lot. And pardon me if it is so obvious as I've just started learning Django.
logic.py
global table
table = {}
for i in range(9):
for j in range(9):
key = 'i'
key = key + str(i)+str(j)
table[key]=0
views.py
from .logic import table
# Create your views here.
def sudokuf(request):
title = "Sudoku Puzzle"
if request.method == 'POST' :
print(request.POST) # here I want to read the puzzle data and solve it
return render (request,"sudoku.html",table)
sudoku.html
<form method="POST" action=""> {% csrf_token %}
{% include "table.html" %}
<input type="submit" align="centre" value="Solve">
</form>
table.html
<table class="sudoku" align="center">
<tr>
{% if i00 %}
<td id="i0_0" class="static">{{i00}}</td>
{% else %}
<td id="i0_0" class="edit"><input id="i00" maxlength="1" autocomplete= "off"></td>
{% endif %}
{% if i01 %}
<td id="i0_1" class="static">{{i01}}</td>
{% else %}
<td id="i0_1" class="edit"><input id="i01" maxlength="1" autocomplete= "off"></td>
{% endif %}
{% if i02 %}
<td id="i0_2" class="static">{{i02}}</td>
{% else %}
and so on....
But I'm getting the same dictionary as I sent(with all 0s as value), as context variable, after clicking 'Solve'.
Firstly, you need to actually look in request.POST:
if request.method == 'POST' :
print(request.POST) # not 'table'
But secondly, your form fields do not have name attributes, so they won't even be sent in the POST to begin with. You need to add those attributes:
<input id="i00" name="i00" maxlength="1" autocomplete= "off"