I'm trying to prevent/allow the user from clicking a button depending on whether a key is present in the request.session data.
It works for blocking it, but once the key is added to the session, that isn't reflected on the webpage/template and the key remains blocked. I presume I'll have to do this in JS but I'm not sure how to approach it. Any ideas?
Thanks
{% if choices not in request.session %}
<form class="submit-form" action="{% url 'search' %}" method="post" onsubmit="return false;">
{% csrf_token %}
<input type="submit" class="show-more-button cunt" style="margin-left: 5px" name="mybtn"
value="Search" data-bs-toggle="popover"
data-bs-placement="right" data-bs-trigger="focus"
data-bs-content="Please select one or more ingredient">
</form>
{% else %}
<form action="{% url 'search' %}" method="post">
{% csrf_token %}
<input type="submit" class="show-more-button" style="margin-left: 5px" name="mybtn"
value="Search">
</form>
{% endif %}
if request.POST.get('button_color') == 'green':
selected_ingredients = request.session.get('choices', [])
selected_ingredients.insert(len(selected_ingredients), ingredients_name)
request.session['choices'] = selected_ingredients
request.session.modified = True
Related
I'm working on a quiz app and want to generate a number of input fields representing the answers based on the value that the user types.
I'm using a button named "create" to do that Using JavaScript, but when clicking the button it submits the form.
Please Check the two images below.
Input
Output
HTML Code
{% load static %}
{% block body %}
<button class="btn btn-primary new">Add a question</button>
<form class="question" method="POST" style="display: none">
{% csrf_token %}
<div class="form-group">
<label for="exampleInputEmail1">Title</label>
<input type="text" class="form-control" id="title" placeholder="Question title">
</div>
<div class="form-group" id="answers_num">
<label for="exampleInputPassword1">Number of answers</label>
<input type="number" class="form-control" id="ans_number">
<button class="create_answers">Create</button>
</div>
<div class="form-group">
{% comment %} Generated input fields {% endcomment %}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% block script %}
<script src="{% static 'mcq/index.js' %}"></script>
{% endblock %}
{% endblock %}```
JS code
document.querySelector(".new").addEventListener("click", ()=> {
document.querySelector(".question").style.display = 'block';
document.querySelector("#create_answers").addEventListener("click", ()=> {
answers = this.value;
console.log(answers);
// Create input fields
for (let i = 0; i < answers; i++) {
input = document.createElement("input");
input.classList.add('form-control');
answersDiv = document.querySelector("#answers").appendChild(input);
}
})
})```
You need to explicitly set the type of the button, like
<button class="create_answers" type="button">Create</button>
in order to avoid submitting the form upon click.
Based on the following image, I am trying to make the fields category and current points non-editable when the status of the task is Finalized or Cancelled, otherwise the fields should be editable.
Below is the code from my html file.
{% extends "base.html" %} {% load widget_tweaks %}
{% block content %}
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<label>Select your category</label>
{{ form.category|add_class:"card" }}
<label>What's the status of the task?</label>
{{ form.status|add_class:"card" }}
<label>Current points:</label>
{{ form.points|add_class:"card" }}
<label>Finalized date:</label>
{{ form.ending_date|add_class:"card" }}
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
Below is the code from my forms.py file.
class TaskModelForm(forms.ModelForm):
class Meta:
model= Task
fields = ['category', 'status', 'points']
def __init__(self, *args, **kwargs):
super(TaskModelForm, self).__init__(*args, **kwargs)
self.fields['status'].required = False
self.fields['points'].required = False
When I want to edit the contents of this form I need to verify if the status is Finalized, so the fields are non-editable, otherwise the fields should be editable and I am thinking something about:
{% extends "base.html" %} {% load widget_tweaks %}
{% block content %}
{% if form.status.value == 'Active' %} <!--make the fields editable -->
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<label>Select your category</label>
{{ form.category|add_class:"card" }}
...
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
{% endif %}
{% if form.status.value == 'Finalized' %} <!--make the fields non-editable -->
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<label>Select your category</label>
{{ form.category|add_class:"card" }}
...
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
{% endif %}
However, I believe my approach might not work because this could be a more front-end problem rather than back-end one (just a guess). Can you point me out to the right direction to solve this problem?
Since the status is something that the user selects, you can't address your requirement with Python (Django) running on the server. You have to address it with a JavaScript running in the web page that displays the form. Something like this will definitely do the trick.
{% extends "base.html" %} {% load widget_tweaks %}
{% block content %}
<body onload="makeReadOnly();">
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<div class="tweet-composer">
<label>Insert your task</label>
{{ form.task|add_class:"card js-keeper-editor" }}
</div>
<label>Select your category</label>
{{ form.category|add_class:"card" }}
<label>Current points:</label>
{{ form.points|add_class:"card" }}
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
</body>
{% endblock content %}
<script type="text/javascript">
{% block jquery %}
function makeReadOnly()
{
if (document.getElementById('id_status').value == 'Finalized'){
document.getElementById('id_task').readOnly=true;
document.getElementById('id_category').readOnly=true;
}else if (document.getElementById('id_status').value == 'Active'){
document.getElementById('id_task').readOnly=true;
document.getElementById('id_category').readOnly=false;
}
}
document.getElementById('id_status').addEventListener('change', makeReadOnly);
{% endblock %}
</script>
With the "view page source" you can see the HTML structure that Django generates out of your form, so that you can identify the right bits with JQuery selectors. Alternatively you can do
f = SomethingForm()
f.as_p()
in the ./manage.py shell console.
At the Django end, you may need custom form validation to handle the inter-dependency between the value of status and whether the other fields are required or not.
I'm using django form and it's defined like this:
class SrtForm(forms.Form):
text = forms.CharField(
widget=forms.Textarea(attrs={'cols': 50, 'rows': 200}))
def __init__(self, *args, **kwargs):
super(SrtForm, self).__init__(*args, **kwargs)
self.fields['text'].label = ''
Then I use it in html like this:
<div class="col-md-6 form-group">
<form action="" method="post">
{% csrf_token %}
{% bootstrap_form en_form %}
</form>
</div>
<div class="col-md-6 form-group">
<form action="{% url 'edit_space:edit_srt' video_id %}" method="post">
{% csrf_token %}
{% bootstrap_form zh_form %}
{% if task_status == 'taken_by_me' %}
{% buttons %}
<button name="submit" class="btn btn-primary">submit changes</button>
{% endbuttons %}
{% endif %}
</form>
</div>
Then I got two forms shown 50/50 at the same row. Like this:
see picture here
Each form has its own scrollbar. What I want to achieve is when I drag one of the two scrollbars, the other side scrolls synchronously. Is there any way to do that in django form in detail?
Any answers would be appreciated. :)
I am new to django forms and while trying to design an HTML form, I notice that the django form blocks are not displaying. Below are the codes:
<body> tag of index.html:
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-login">
<div class="panel-heading">
<div class="row">
<div class="col-xs-6">
Login
</div>
<div class="col-xs-6">
Register
</div>
</div>
<hr>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
{% block login_content %}
{% endblock %}
{% block register_content %}
{% endblock %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
login.html which goes into the {% block login_content %}
{% extends 'index.html' %}
{% block login_content %}
<form id="login-form" action="{% url 'authentication:user_login' %}" role="form" style="display: block;" method="POST">
{% csrf_token %}
<label for="username">Username:</label>
<input id="username" type="text" name="username" placeholder="Enter Username" tabindex="1" class="form-control">
<label for="password">Password:</label>
<input id="password" type="password" name="password" tabindex="=2" class="form-control" placeholder="Password">
<button type="submit" class="btn btn-success">Login</button>
</form>
{% endblock %}
register.html that goes into the {% block register_content %}
{% extends 'index.html' %}
{% block register_content %}
<form id="register-form" role="form" style="display: none;" enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<input type="submit" name="" value="Register">
</form>
{% endblock %}
On my UI, the {{ user_form.as_p }} and the {{ profile_form.as_p }} does not appear at all.
When i inspect the console of my UI, the html does not even pick up the following line from the register.html:
<form id="register-form" role="form" style="display: none;" enctype="multipart/form-data" method="POST">
Here is the login.js which is responsible for the UI interactivity:
$(function() {
$('#login-form-link').click(function(e) {
$("#login-form").delay(100).fadeIn(100);
$("#register-form").fadeOut(100);
$('#register-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
});
$('#register-form-link').click(function(e) {
$("#register-form").delay(100).fadeIn(100);
$("#login-form").fadeOut(100);
$('#login-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
});
});
EDIT:
Here is my views.py:
def user_login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('homepage')) # main page if login is successful
else:
return HttpResponse("ACCOUNT NOT ACTIVE")
else:
print('Someone tried to log in and failed')
print('Username: {}, password, {}'.format(username, password))
return HttpResponse('Invalid login details supplied')
else:
return render(request, 'authentication/login.html', {})
def register(request):
registered = False
if request.method == "POST":
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
registered = True
else:
print(user_form.errors, profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileInfoForm()
return render(request, 'authentication/register.html',
{
'user_form': user_form,
'profile_form': profile_form,
'registered': registered
})
Okay, it seems like it is impossible to have a single page display both the templates. Is there anyway to get it done?
In your register.html,
<form id="register-form" role="form" style="display: none;" enctype="multipart/form-data" method="POST">
You are setting style="display: none;", so obviously the form won't show up.
EDIT: I am not sure about the feasibility of showing two different forms in the same page.
I have a form with two submit buttons, I am validating the form with jquery validate and submitting it. I want to know at server which button was clicked.
Form
<form class="dp-blog-form" action="{% url 'price_assessment_section_1' component.id %}" method="post"> {% csrf_token %}
{{ form.as_p }}
<!-- FORM SUBMIT BUTTONS-->
<button type="submit" > Save&Home</button>
<button type="submit" > Save&Next</button>
</form> <!-- end form-->
JS
$('.dp-blog-form button[type="submit"]').on('click', function (e) {
e.preventDefault();
if ($('.dp-blog-form').valid()) {
unbindPageLeaveEvent();
disableButton($(this));
$('.dp-blog-form').submit();
}
});
How to get the button information at the sever?
You can add a hidden field in the form, in the line just above the submit, which will be sent along:
$('.dp-blog-form').append('<input type="hidden" name="theButton" value="'+ this.textContent +'"/>');
set value and name for button, you can access it from server.
<form class="dp-blog-form" action="{% url 'price_assessment_section_1' component.id %}" method="post"> {% csrf_token %}
{{ form.as_p }}
<!-- FORM SUBMIT BUTTONS-->
<button type="submit" name='action' value='save_home'> Save&Home</button>
<button type="submit" name='action' value='save_next' > Save&Next</button>
</form> <!-- end form-->
we can add hidden field in a form:
<form class="dp-blog-form" action="{% url 'price_assessment_section_1' component.id %}" method="post"> {% csrf_token %}
{{ form.as_p }}
<!-- FORM SUBMIT BUTTONS-->
<input type="hidden" name="button_clicked" />
<button type="submit" name='action' value='save_home'> Save&Home</button>
<button type="submit" name='action' value='save_next' > Save&Next</button>
</form> <!-- end form-->
and in JS please set the value of clicked button into hidden field. then you will able to get the value of clicked button on server ...