MrHize
MrHize

Reputation: 220

How do I toggle boolean field

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.

enter image description here

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>

Upvotes: 0

Views: 3236

Answers (2)

Achuth Varghese
Achuth Varghese

Reputation: 2451

  1. 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>
  1. 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"),
  1. 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)

enter image description here enter image description here

Upvotes: 3

Lomtrur
Lomtrur

Reputation: 1798

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")

Upvotes: 0

Related Questions