How do I toggle boolean field - python

I am working on a project where user have his own profile, I want to create a BooleanField on model so that user can set profile privacy, private or public. I have added a BooleanField to modal (is_private). Also i have a toggle switch on template but i do not know how to go with it with Django. I want when a user click on switch boolean field is true (private), when user click again on switch boolean field is false (public). Jquery maybe needed as well.
Model:
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,blank=True,null=True)
is_private = models.BooleanField(default=False)
Views:
def profile_edit_view(request):
p = Profile.objects.filter(user=request.user).order_by('-id')
context = {'p':p}
return render(request, 'profile_edit.html', context)
urls:
path('account/edit/', profile_edit_view, name ='profile-edit'),
Profile Edit Template:
<form method="POST" name="is_private">
{% csrf_token %}
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="customSwitches" name="is_private">
<label class="custom-control-label" for="customSwitches">Private Account</label>
</div>
</form>
<p class="text-muted font-weight-normal font-small">
When your account is private, only people you approve can see your photos and videows on Pixmate. Your existing followers won't be affected.
</p>

In template file change the input tag as shown
<!-- Mark the checkbox as checked or not by is_private -->
<input type="checkbox" class="custom-control-input" id="customSwitches" {% if p.is_private %}checked{% endif %}>
In that same template file add this script
<script type="text/javascript">
$(document).ready(function() {
// send request to change the is_private state on customSwitches toggle
$("#customSwitches").on("change", function() {
$.ajax({
url: "{% url 'change_privacy' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
is_private: this.checked // true if checked else false
},
type: "POST",
dataType : "json",
})
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
.done(function(data) {
console.log(data);
// show some message according to the response.
// For eg. A message box showing that the status has been changed
})
.always(function() {
console.log('[Done]');
})
})
});
</script>
Add a new path in your urls file of the app which binds to a view. Say: a function named change_privacy() in your views
path('changeprivacy', change_privacy, name="change_privacy"),
In views file add a new function. You need to import JsonResponse
from django.http import JsonResponse
def change_privacy(request):
if request.is_ajax() and request.method=='POST':
profile = Profile.objects.get(user=request.user)
profile.is_private = True if request.POST.get('is_private') == 'true' else False
profile.save()
data = {'status':'success', 'is_private':profile.is_private}
return JsonResponse(data, status=200)
else:
data = {'status':'error'}
return JsonResponse(data, status=400)

Here is how to do it with Ajax.
First include jQuery:
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
Ajax setup, you need to include a CSRF token (or make decorate your view with #csrf_exempt). Relevant section in the django documentation. If you don't include the CSRF token in your request you will get 403 Forbidden.
<script type="text/javascript">
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
</script>
Then make the Ajax request:
<script type="text/javascript">
$("document").ready(function () {
$("#customSwitches").change(function () {
$.ajax({
type: "POST",
headers: {
"X-CSRFToken": csrftoken
},
url: {% url 'privacy' %},
data: {
"enabled": this.checked,
},
success: function (data) {
console.log(data);
},
error: function (data, msg) {
console.log("ERROR", data, msg);
}
});
})
});
</script>
Adjust the url to work with your project and don't forget to include the CSRF token in the header.
Then you can get the value of the checkbox in your view and update the value for your user:
def privacy_view(request):
if request.is_ajax():
enabled = request.POST["enabled"]
profile = Profile.objects.get_or_create(user=request.user)
profile.is_private = enabled
profile.save()
return render(request, "privacy.html")

Related

Django is not taking GET input in AJAX call

I am trying to take username input and return in ajax call whether the username is taken or not in Django. But the method in DJango is not taking the input. I am sharing the code here.
URL.py
url(r'^search_username/$', user.views.search_product, name="search_username"),
script + HTML
{% load staticfiles %}
{% block content %}
<form method="post">
{% csrf_token %}
<input name="search" id="search" type="text"/>
<button type="submit">Sign up</button>
</form>
{% endblock %}
$("#search").change(function () {
var username = $(this).val();
$.ajax({
url: '/search_username/',
data: {
'username': username
},
dataType: 'json',
error: function(){
alert('failure');
},
success: function (data) {
if (data.is_taken) {
alert("A user with this username already exists.");
}
}
});
});
Views.py
def search_username(request):
print('Entered into search')
username = request.GET.get('search', None)
print(username)
data = {
'is_taken': allproductlist.objects.filter(product_name_english__iexact=username).exists()
}
return JsonResponse(data)
The problem is it prints Entered into search.But when I print username it shows NOne. Can anyone please specify what is happening ?
Your Ajax is sending the data as "username" but your Python is looking for "search".
you are sending username in ajax request but you are getting search in views.py.
you can Update your ajax code:
$("#search").change(function () {
var username = $(this).val();
$.ajax({
url: '/search_username/',
data: {
'search': username
},
dataType: 'json',
error: function(){
alert('failure');
},
success: function (data) {
if (data.is_taken) {
alert("A user with this username already exists.");
}
}
});
});
2nd way is that you can change in views.py.
username = request.GET.get('username', None)

Flask: POST request using AJAX

I want to make a post request by using ajax. I want to use the input value as function parameter and append the function return into a html table. I don't know but a think that my code is wrong and the ajax is not working.
Note: For testing, I'm taking input value and returning to html page.
network.html
<script type="text/javascript">
$(function(){
$('#button').click(function(){
var dados = $('#search-input').val();
$.ajax({
url: '/network',
data: $('form').serialize(),
type: 'POST',
success: function(data){
$('#result').append(data)
console.log(data);
},
error: function(error){
console.log(error);
}
});
});
});
</script>
<form name='form' method="POST">
<input type="text" name="search-input" id="search-input" class="form-control" placeholder="Users and ID" >
<button type="submit" class="btn btn-primary" id="button">Search</button>
</form>
<span id=result>{% print dado %}</span>
app.py
#app.route('/network',methods=['POST','GET'])
def network():
if request.method == 'POST':
input = request.form['search-input']
return render_template('network.html',dado=input)
else:
return render_template('network.html',dado='')
Edit: After this update what's returning is a JSON format
{
"dado": "INPUT VALUE"
}
app.py
#app.route('/network',methods=['POST','GET'])
def network():
if request.method == 'POST':
input = request.form['search-input']
return jsonify(dado=input)
else:
return render_template('network.html',dado='')
network.html
<script type="text/javascript">
$(function(){
$('#botao').click(function(){
var dados = $('#search-input').val();
$.ajax({
url: "{{ url_for('network') }}",
data: JSON.stringify(dados),
contentType: 'application/json;charset=UTF-8',
type: 'POST',
success: function(data){
$('#result').append(data["dado"])
console.log(data);
},
error: function(error){
console.log(error);
}
});
});
});
</script>
You got to return JSON!
Instead of return render_template(...), use:
return jsonify(dado = input)
Then in your ajax success call:
success: function(data){
$('#result').append(data["dado"])
console.log(data);
}
...
}); // end AJAX
e.preventDefault();
Don't forget to import jsonify
from flask import jsonify

How to use bootbox for Django DeleteView?

I am using Django DeleteView for deleting objects. First, I implemented delete add confirm dialog redirecting another html page. Now, I want to add bootbox pop up. But i don't understand where to add code. Please help
models.py
class Review(models.Model):
review_description = models.TextField(max_length=500)
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
views.py
class ReviewDelete(DeleteView):
model = Review
template_name = "confirm_delete.html"
def get_success_url(self, *args, **kwargs):
review = get_object_or_404(Review, pk=self.kwargs['pk'])
return reverse("books:detail", args = (review.book.id,))
confirm_delete.html
{% extends "base.html" %}
{% block content %}
<h1>Delete</h1>
<p>Are you sure you want to delete {{ review }}?</p>
<form action="{% url "delete" pk=review.id %}" method="POST">
{% csrf_token %}
<input type="submit" value="Yes, delete." />
No, cancel.
</form>
{% endblock %}
book_details.html
Delete
{# Delete#}
base.html
<script type="text/javascript">
$(document).ready(function () {
$("#review-delete-btn").click(function (event) {
event.preventDefault();
bootbox.confirm({
title: "Destroy planet?",
message: "Do you want to delete? This cannot be undone.",
buttons: {
cancel: {
label: '<i class="fa fa-times"></i> Cancel'
},
confirm: {
label: '<i class="fa fa-check"></i> Confirm'
}
},
callback: function (result) {
console.log('This was logged in the callback: ' + result);
}
});
});
});
</script>
urls.py
url(r'^reviews/(?P<pk>\d+)/delete/$', ReviewDelete.as_view(), name='delete'),
Assuming your server page doesn't perform redirects when completing the delete, you just need to add an AJAX call to the confirm callback. Something like this:
<script>
$(function () {
$("#review-delete-btn").on('click', function (event) {
event.preventDefault();
// for referencing this later in this function
var _button = $(this);
bootbox.confirm({
title: "Destroy planet?",
message: "Do you want to delete? This cannot be undone.",
buttons: {
cancel: {
label: '<i class="fa fa-times"></i> Cancel'
},
confirm: {
label: '<i class="fa fa-check"></i> Confirm'
}
},
callback: function (result) {
// result will be a Boolean value
if(result){
// this encodes the form data
var data = _button.closest('form').serialize();
$.post('your delete URL here', data).
done(function(response, status, jqxhr){
// status code 200 response
})
.fail(function(jqxhr, status, errorThrown){
// any other status code, including 30x (redirects)
});
}
}
});
});
});
</script>
You will probably want to review the documentation for $.post and serialize. I would also recommend working your way through the AJAX topics - $.post is a convenience method for $.ajax, so you should know how to use both.

(Django) Edit db.sqlite3 database on a HTML Contenteditable table using Ajax

I'm trying to create an content editable HTML table that'll update the db.sqlite3 database on keypress. The table can't have an input field in it because I also require it to be able to be filter and search using data-tables. so far I manage to retrieve the input on enter keypress but i don't know how to POST it straight to database (Presumably using AJAX) instead of JSON. Can anyone provide me with complete syntax sample as well, I'm very new to Django
Here's my code :
Model.py
class MyModel(models.Model):
a = models.CharField(max_length=10)
b = models.CharField(max_length=10)
def __str__(self):
return self.a
form.py
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ['a', 'b']
view.py
def display_table(request):
context = {
"table_list": MyModel.objects.all(),
"title": "Table_List"
}
return render(request, 'tables/display.html', context)
display.html
<form action="" method="post" id="test_post">{% csrf_token %}
<div id="debug" contenteditable data-name="custom-text">Some text you can edit.</div>
<table id="myTable" class="display">
<thead>
<tr>
<th>A</th>
<th>B</th>
</tr>
</thead>
<tbody>
{% for data in table_list %}
<tr >
<td contenteditable="true" data-name="a_name" id="{{data.id}}">{{data.a}}</td>{% csrf_token %}
<td contenteditable="true" data-name="b_name" >{{data.b}}</td>{% csrf_token %}
</tr>
{% endfor %}
</tbody>
</table>
</form>
<script>
document.addEventListener('keydown', function (event) {
var esc = event.which == 27,
nl = event.which == 13,
el = event.target,
data = {};
if (esc) {
// restore state
document.execCommand('undo');
el.blur();
} else if (nl) {
// save
data[el.getAttribute('data-name')] = el.innerHTML;
// we could send an ajax request to update the field
$.ajax({
data: data,
type: "POST"
});
log(JSON.stringify(data));
el.blur();
event.preventDefault();
}
}, true);
function log(s) {
document.getElementById('debug').innerHTML = 'value changed to: ' + s;
console.log(s);
}
</script>
<script>
$(document).ready(function(){
$('#myTable').DataTable();
});
</script>
Thank you very much for everyone's help.
Yes you're right about using AJAX. A few things you will need to modify:
1. Your HTML/JS
$.ajax({
data: data,
type: "POST",
// include URL
url: 'url/to/post/to',
// include response handler here
success: function(response) {
// do whatever you want with response
// you can just console.log(response.data) first
},
error: function(response) {
// error handler to failed AJAX requests
}
});
2. Views
You'll need to change your view to return a JsonResponse instead of using render which creates an HTML response. Note that the JsonResponse will be the exact response received in the AJAX handler above.
Hope this helps.

Forbidden (CSRF token missing or incorrect.)

I've searched through similar questions, but nothing seems relevant to my situation.
Why does this code work fine:
<form action="/signup/" method="post">
{% csrf_token %}
[FORM]
</form>
but
<form id="signup-form">
{% csrf_token %}
[FORM]
</form>
<script type="text/javascript">
$(function() {
$(".submit-signup").on("click", function() {
var user = $("#signup_form").serialize();
console.log(user);
$.post("/signup/", user, function() {
});
});
});
</script>
not work?
Here is signup in views.py:
#requires_csrf_token
def signup(request):
[STUFF]
return render(request, 'signup.html', {[STUFF}})
What else can I provide that would help? Basically I am trying to take a page and turn it into a modal that does the same thing.
Thanks!
you are doing an ajax post call for which you need to give csrf token also:
$.post("/signup/", {
user: user,
csrfmiddlewaretoken: '{{ csrf_token }}'
}, function() {
// success todo
}, function(){
// fail todo
});

Categories

Resources