Creating a modal popup in django_tables2 - django

I am trying to add an edit button that brings up a modal in django_tables2. The first entry in the table behaves correctly but the subsequent entries do no result in a modal popup. When I inspect the buttons, the first shows an event while the rest do not. Any ideas why the behavior isn't repeating.
tables.py
import django_tables2 as tables
from .models import expenseModel
from django_tables2 import TemplateColumn
class expenseTable(tables.Table):
class Meta:
model = expenseModel
template_name = "django_tables2/bootstrap.html"
fields = ('vendor', 'date', 'amount', 'category', 'description')
edit = TemplateColumn(template_name = 'edit_button.html')
edit_button.html
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
</head>
<body>
<button id='editBtn'>Edit</button>
<div id='myModal' class='modal'>
<div class='modal-content'>
<span class='close'>×</span>
<p>Some Text in the modal</p>
<form action="/summary/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="submit">
</form>
</div>
</div>
<script>
let modal = document.getElementById("myModal");
let btn = document.getElementById("editBtn");
let span = document.getElementsByClassName("close")[0];
btn.onclick = function() {
modal.style.display="block";
}
span.onclick = function() {
modal.style.display="none";
}
window.onclick = function() {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
</body>
The first button shows this:
The second button shows this:

You should use the same value for ID multiple times. ID should always use unique values where e.g. class can share the same value multiple times.
Check https://stackoverflow.com/a/753183/4151233

Related

Django ChoiceField RadioSelect widget in form, test whitch element selected in template

I have 2 radio buttons in a ChoiceField and I would like to display some parts of the template, depending of witch radio button is selected.
Following :
form.py
class CtdForm(forms.Form):
protocol_name = forms.CharField(max_length=100)
rb = forms.BooleanField(required=False, label='RB')
mr = forms.BooleanField(required=False, label='MR')
CHOICES = [('rb' ,'RB'), ('mr', 'MR')]
analyse_type = forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect)
template html
...
{{ form.analyse_type }}
Here I would like to test which button is selected and display the template depending of the selection
something like : {% if form.analyse_type.? == true %}
...
I test a lot of syntaxe with form.analyse_type.? like form.analyse_type.field.widget.choices to have each choices in a loop ect. , but I do not found the right one returning the selected radiobutton...
Maybe this way is not the right one to do what I want.
If you have any idea, solution thank you ;)
Edit for user2497126
Thanks for all tips :) !
I have an error Uncaught Error: GET_ELEMENTS: -> form[data-sb-form-api-token] seems to be in link with the object analyse_type
As requested, following a print screen with the html element.I tired different synthaxe like
let radioValue =$("input[name='analyse_type']:checked").value();
I also put my HTML code in case
{% extends "index.html" %}
{% load static %}
{% block content %}
<div style="padding-left: 30%;" class="col-lg-6 col-xl-6"
<h2 class="h4 fw-bolder">
Analyse Type
</h2>
<br>
{{ form.analyse_type }}
<br> </div>
<div id="template-one" style="display:none;">
<div style="padding-right: 30%;" class="col-lg-6 col-xl-6">
<h2 class="h4 fw-bolder">
TEST
</h2>
</div>
</div>
{% endblock %}
{% block javascript %}
<script type="text/javascript">
$(document).ready(function () {
$(".custom-control-input").change(function () {
let radioValue = $("input[name='analyse_type']:checked").value();
let templateOne = document.getElementById('template-one')
if (radioValue == "rb") {
$("#template-one").show();
} else {
$("#template-one").hide();
}
});
});
</script>
{% endblock javascript %}
EDIT
if I do a
console.log($("input[name='analyse_type']:checked").val())
in the debugger of chrome I have a return of rb.
But the error is still there with no result.
I also change the html, include the template-one in the same div of the form like your example
The problem seems here
$(".custom-control-input").change(function () {
I replace .custom by select or select#id_analyse_type, based on some forum answers, but I have no result
Thanks for your time and your help :)
EDIT
Here the solution :
{% block javascript %}
<script type="text/javascript">
$(document).ready(function () {
let radioValue = $("input[name='analyse_type']:checked").val();
if (radioValue == "rb") {
$("#template-one").show();
} else {
$("#template-one").hide();
}
$('#id_analyse_type').change(function () {
let radioValue = $("input[name='analyse_type']:checked").val();
if (radioValue == "rb") {
$("#template-one").show();
} else {
$("#template-one").hide();
}
});
});
</script>
{% endblock javascript %}
Thank you for your help !
Here is an edited answer which I have tried to adapt to your question
For the change function (i.e when selecting the radio) inspect and replace the class value with the one in your radio input. Also ensure you supply the correct name when instantiating the variable radioValue, I have used 'analyze_type' for the sake of the example but inspect and confirm the correct name value of the radio input.
You can achieve it using JS like this in your template
{% extends "base.html" %}
{% block title %}Form title{% endblock title %}
{% block content %}
<!-- page content -->
<div class="x_content">
{{ form.analyse_type}}
<div id="template-one" style="display:none;">
Template one
</div>
<div id="template-two" style="display:none;">
Template two
</div>
</div>
<!-- /page content -->
{% endblock %}
{% block javascript %}
<script>
$(document).ready(function(){
$(".custom-control-input").change(function(){
let radioValue = $("input[name='analyse_type']:checked").val();
let templateOne = document.getElementById('template-one')
if(radioValue == "RB"){
$("#template-one").show();
$("#template-two").hide();
}
else {
$("#template-two").show();
$("#template-one").hide();
}
});
});
</script>
{% endblock javascript %}

I want to get e-mail authentication

An authentication number function that generates eight random characters was implemented.
i inputted username, and mail. because i want to write searching password html and request it at view with Ajax.
When I enter my username and email, I want the authentication number to be sent to the email. At the same time, the code created in ajax should show the authentication number window.
but, it happened nothing.
what should i do...?
help me!
error is Uncaught SyntaxError: Unexpected token '<' WHAT'S THAT..?
First of all, I corrected the white page. I missed it. '>'
#html
{% load static %}
<!DOCTYPE html>
<html lang="KO">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="{% static 'users/css/recovery_pw.css' %}" rel="stylesheet">
<link href="{% static 'users/css/default.css' %}" rel="stylesheet">
<script
src="https://kit.fontawesome.com/96379a54a1.js"
crossorigin="anonymous"
></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="{% static 'users/js/recovery_pw.js' %}" </script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
{% block content %}
<form method="get" enctype="multipart/form-data">
<div class="container">
<div class="inner-box">
<div class="title">
<h1>비밀번호 찾기</h1>
</div>
<div class="input-box">
<div class="id">
<input type="email" placeholder="등록하신 메일로 인증번호가 발송됩니다." name="email" maxlenth="20" autocomplete="off" value="{{ form.email.value|default_if_none:'' }}" required />
</div>
<div class="password">
<input type="username" placeholder="아이디를 입력하세요" name="username" maxlength="20" value="{{ form.username.value|default_if_none:'' }}" required />
</div>
</div>
<div class="btn">
<div class="btn-white" id="btn_white"><button type="submit">임시 비밀번호 발송</button></div>
</div>
<div class="loading-box">
<div id="loading"></div>
</div>
</div>
</form>
{% endblock %}
</body>
</html>
#users/js/recovery_pw.js
$(document).ready(function () {
$('#find_pw').click(function () {
$('#loading').replaceWith('<div id="loading_end" class="loading"></div>')
// 걍 임의로 만든것 같음
var name = $("#pw_form_name").val();
var email = $("#pw_form_email").val();
$.ajax({
type: "POST",
url: "/users/recovery/pw/find/",
dataType: "json",
data: {
'name': name,
'email': email,
'csrfmiddlewaretoken': '{{csrf_token}}',
},
success: function (response) {
// loading_end 이걸 지움
$('#loading_end').remove()
alert('회원님의 이메일로 인증코드를 발송하였습니다.');
// 나는 이메일전송버튼이지
$('#btn_white').remove()
$('#result_pw').replaceWith(
'<hr><div class="row justify-content-md-center"><form class="form-inline" style="margin-bottom:-15px; margin-top:-10px;"><div class="md-form md-outline"><label for="input_auth_num">인증번호 입력 (<span id="timeset"></span>)</label><input type="text" id="input_auth_num" class="form-control mx-sm-2" autofocus/></div></form>' +
'<button type="submit" name="auth_confirm" id="id_auth_confirm" class="btn btn-red" style="opacity: 90%; height:30%; margin-top:10px; font-size: 12px;"><i class="fas fa-check"></i> 인증확인</button></div><hr>'
)
function countdown(elementName, minutes, seconds) {
var elementName, endTime, hours, mins, msLeft, time;
function twoDigits(n) {
return (n <= 9 ? "0" + n : n);
}
function updateTimer() {
msLeft = endTime - (+new Date);
if (msLeft < 1000) {
alert("인증시간이 초과되었습니다.");
$("" + elementName).remove();
cert_ok = false;
certificationNum = false;
location.href = "{% url 'recovery_pw' %}"
} else {
time = new Date(msLeft);
hours = time.getUTCHours();
mins = time.getUTCMinutes();
$("" + elementName).html((hours ? hours + ':' + twoDigits(mins) : twoDigits(mins))
+ ':' + twoDigits(time.getUTCSeconds()));
setTimeout(updateTimer, time.getUTCMilliseconds() + 500);
}
}
endTime = (+new Date) + 1000 * (60 * minutes + seconds) + 500;
updateTimer();
}
countdown("#timeset", 5, 0);
var user = response.result
$(document).ready(function () {
$('#id_auth_confirm').click(function () {
var input_auth_num = $("#input_auth_num").val();
$.ajax({
type: "POST",
url: "/users/recovery/pw/auth/",
dataType: "json",
data: {
'input_auth_num': input_auth_num,
'csrfmiddlewaretoken': '{{csrf_token}}',
},
success: function (response) {
location.href = "{% url 'recovery_pw_reset' %}";
},
error: function () {
if ($('#input_auth_num').val() == "") {
alert('회원님의 이메일로 전송된 인증번호를 입력해주세요.');
} else {
alert('인증번호가 일치하지 않습니다.');
}
},
});
})
})
},
error: function () {
$('#loading_end').remove()
if (username == "" || email == "") {
alert('이름, 이메일을 모두 입력해주세요.');
} else {
alert('입력하신 정보가 일치하지 않거나 존재하지 않습니다.');
}
},
});
})
});
#views.py
class RecoveryPwView(View):
template_name = 'users/recovery_pw.html'
recovery_pw = RecoveryPwForm
def get(self, request):
if request.method=='GET':
form = self.recovery_pw(None)
return render(request, self.template_name, { 'form':form, })
def ajax_find_pw_view(request):
username = request.POST.get('username')
email = request.POST.get('email')
target_user = User.objects.get(username=username, email=email)
if target_user:
auth_num = email_auth_num()
target_user.auth = auth_num
target_user.save()
send_mail(
'this is email verify',
['email'],
html=render_to_string('users/recovery_email.html', {
'auth_num': auth_num,
}),
)
return HttpResponse(json.dumps({"result": target_user.username}, cls=DjangoJSONEncoder), content_type = "application/json")
#urls.py
path('recovery/pw/', RecoveryPwView.as_view(), name='recovery_pw'),
path('recovery/pw/find/', views.ajax_find_pw_view, name='ajax_pw'),
path('recovery/pw/auth/', views.auth_confirm_view, name='recovery_auth'),
path('recovery/pw/reset/', views.auth_pw_reset_view, name='recovery_pw_reset'),
form
class RecoveryPwForm(forms.Form):
username = forms.CharField(label='id')
email = forms.EmailField(label='email')
class Meta:
fields = ['username', 'email']
class CustomSetPasswordForm(forms.Form):
new_password = forms.CharField(
max_length=16,
min_length=6,
label=_('새 비밀번호')
)
confirm_password = forms.CharField(
max_length=16,
min_length=6,
label=_('새 비밀번호 확인')
)
since you are using the get method into the View model, you can use it directly without checking by method and that is what that function does for ease
Note:-
now you handle the request method by get method which you can't use csrf_token into your form
now the problem is that, you are trying to use get method to send data then, you want to get this data in ajax by Post method which you won't receive any data of course in addition to, that you are trying to execute the separate function in the view which cause a problem where the function will never execute because the form doesn't know where should it send the data in after the request is created.
so, now you can remove the additional function you use and try to use and include what you want in the one view to prevent the confusion so, follow the solution like so:
class RecoveryPwView(View):
template_name = 'users/recovery_pw.html'
recovery_pw = RecoveryPwForm
def get(self, request):
form = self.recovery_pw(None)
return render(request, self.template_name, { 'form':form})
def post(self, request):
form = self.recovery_pw(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
target_user = User.objects.get(username=username, email=email)
# do send email here
# return the render that you want to finish by post method here
html
<form method="post">
{% csrf_token %}
<div class="container">
<div class="inner-box">
<div class="title">
<h1>비밀번호 찾기</h1>
</div>
<div class="input-box">
{% comment %} <div class="id">
<input type="email" placeholder="등록하신 메일로 인증번호가 발송됩니다." name="email" maxlenth="20" autocomplete="off" value="{{ form.email.value|default_if_none:'' }}" required />
</div>
<div class="username">
<input type="username" placeholder="아이디를 입력하세요" name="username" maxlength="20" value="{{ form.username.value|default_if_none:'' }}" required />
</div> {% endcomment %}
{% for field in form %}
<label>{{ field.label }}</label>
<div>{{ field }}</div>
{% endfor %}
</div>
<div class="btn">
<div class="btn-white" id="btn_white"><button type="submit">임시 비밀번호 발송</button></div>
</div>
<div class="loading-box">
<div id="loading"></div>
</div>
</div>
</form>
Now this solution is not completed, because I'm not sure from understanding exactly what you want to do but at least you can see that there's something new happen for your problem to find the min problem, the issue now will come from Ajax just let me know what you are facing after that

How to place Bokeh widgets precisely on an html page

I am struggling to place Bokeh widgets precisely where I want them on an html page built with Django. For example my views.py look like this:
from bokeh.io import show
from bokeh.layouts import column, row
from bokeh.models import CustomJS, TextInput
from bokeh.plotting import figure
fig = figure(title='title')
fig.line(x=[1,2,3], y=[1,2,3])
text_input = TextInput(title="Add graph title", value='')
text_input.js_on_change('value', CustomJS(
args={'title': fig.title, 'text_input': text_input},
code="title.text = text_input.value"
))
widgets_layout = column(text_input)
figures_layout = row(fig)
#show(row(widgets_layout, fig))
# Set up page layout
page_layout = row(widgets_layout, figures_layout)
script, div = components(page_layout)
return render_to_response('app/test.html', {'script':script, 'div':div})
and my html page (test.html) look like this:
<!--Test page-->
{% extends "base.html" %}
{% load static %}
{% load bootstrap4 %}
{% load i18n %}
{% block content %}
<!--Bokeh-->
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-1.3.4.min.css" rel="stylesheet" type="text/css">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.3.4.min.css" rel="stylesheet" type="text/css">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-tables-1.3.4.min.css" rel="stylesheet" type="text/css">
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-1.3.4.min.js"></script>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.3.4.min.js"></script>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-tables-1.3.4.min.js"></script>
<!--Figure-->
<div class='col-lg'>
<div class='card-lg bg-light' id='maincontent'>
<h2> {% trans "Test" %}</h2>
<hr>
<div>
{{ div | safe }}
{{ script | safe }}
</div>
</div>
</div>
<br>
{% endblock content %}
Now, how can I move the little widget (text_input) to a precise position ? Any position will do, I just want to be able to place it pretty much wherever I want.
Thank you,
You could apply for example spacing (which can also be negative) on the Row and/or on the Column like this:
widgets_layout = column(Div(), row(Div(), text_input, spacing=300), spacing=300)

Django form displays form object as string

I've got a jqGrid that has a button to create a new row. Instead of the Django form that I expect to show up, it just brings up a dialog that says "< views.export_view.ExportTemplateForm instance at 0xb1b2beec>"
HTML:
<div id="add-template-form-div" style="display:none">
<form method="post" name="templateform" id="template-form" title="Template Details">
<table><tbody>
{{export_template_form}}
</tbody></table>
</form>
<div class="form_loading">Adding Template...</div>
<div class="form_error"></div>
<div>
view:
#set other variables
infoDict['export_template_form'] = ExportTemplateForm()
#infoDict gets passed into render_response
class ExportTemplateForm():
id = forms.CharField(widget=forms.HiddenInput())
class Meta(renderutils.BaseModelForm.Meta):
model = ExportTemplate
Any tips?

Question on a jquery-ajax function, Using Django

I am new to Django, Ajax and HTML. I am currently developing a simple website for learning purposes.
The site fetches recent news from my db and displays the 5 latest news entry. This should be done without the user refreshing the whole page.
The code below may not seem much, but it is the the result of a painfully long learning process from my end.
Question comes at the end.
url.py
site_media = '/django/feed/site_media/'
urlpatterns = patterns('',
(r'^$', 'recent.views.recent_feed_view'),
# Site media
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': site_media}),)
models.py
class news(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateField('date published')
views.py
def recent_feed_view(request):
show_results = False
new_feed = []
if 'get_feed' in request.GET:
show_results = True
new_feed = news.objects.order_by('-pub_date')[:5]
variables = RequestContext(request, {
'new_feed': new_feed,
'show_results': show_results,})
if request.GET.has_key('ajax'):
return render_to_response('feed_list.html', variables)
else:
return render_to_response('recent_news.html', variables)
recent_news.html
<html>
<head>
<script type="text/javascript" src="/site_media/jquery.js"> </script>
<script type="text/javascript"src="/site_media/get_feed.js"></script>
</head>
<body>
<form id="search_feed_form" method="get">
<input name = "get_feed" type="submit" value="get_feed" />
</form>
<div id="get_feed_div">
{% if show_results %}
{% include "feed_list.html" %}
{% endif %}
</div>
</body>
</html>
feed_list.html
<ol class="news">
{% for news in new_feed %}
{{ news.question }}
<br />
{% endfor %}
</ol>
get_feed.js
function get_feed_js() {
$('#get_feed_div').load('/?ajax&get_feed');
return false;}
$(document).ready(function () {
$('#search_feed_form').submit(get_feed_js);});
Questions:
1- How can I modify my javascript function so that the page automatically fetches the latest news feed, say every 1 min, without having to press the button?
2- Is there a way to fetch the latest news feed when the user navigates to my website tab? (i.e.: he was currently viewing another tab on his browser and just clicked on the tab with my site on it)
I would greatly appreciate it if I could receive some tips / links to useful materiel that can help me move forward in this endeavor!
Use setInterval: http://www.elated.com/articles/javascript-timers-with-settimeout-and-setinterval/
setInterval('get_feed_js()', 60000); // call func every 60 seconds
$(window).one('focus', function() { // without one, I infinitely get focus event
get_feed_js(); // call function on tab focus
})