popup to edit status_id

Here is a screenshot of my app sofar.

And this is my template:

<!--START SHIFT-->

             <div class="card card-hover" {{ shift.status.color_admin.color_style|safe }} onclick="{{ ??some script here?? }}('{{ shift.id }}')">

                    <div class="inverse container-card">
                        <div class="date-card"><b>{{ shift.start_date|date:'D j M Y' }}</b></div>
                        <div class="time-card">{{ shift.start_time }} - {{ shift.end_time }}</div>
                    </div>

                        <div><b>{{ shift.function }}</b> | {{ shift.shift_title }}</div>
                        <div><i>{{ shift.user.first_name}} {{ shift.user.last_name }}, <b>{{ shift.user.Function_short }}</b></i></div>

                    <div class="flex-container sb">
                        <div>{{ shift.site.Short_value }} - {{ shift.site }}</div>
                    </div>

                 <div class="shiftid">{{ shift.id }}</div>

             </div>

<!--END SHIFT-->

I would like to have an option when clicking the card, to change the status_id of the shift. What steps should I follow to achieve this?

As with anything else affecting the browser UI, you first need to decide if that action needs to happen on the same page or across multiple pages.

If on the same page, you would then be writing JavaScript to handle the click event on those elements and then doing the work.

If across multiple pages, then your cards would be links to the appropriate page where the status can be changed.

I just can’t get this working. Continually gives this error:
“[05/Jul/2023 21:49:29] “GET /shift_info_customer/87/ HTTP/1.1” 200 3226
Not Found: /update_shift_status/87/”

I tried this script:

        <button type="button" onclick="updateShiftStatus(5, {{ shift.id }})">Update Status</button>

<script>
    function updateShiftStatus(newStatus, shiftId) {
        // Send an AJAX request to update the shift status
        const url = '/update_shift_status/' + shiftId + '/';
        const data = {
            status: newStatus
        };

        fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': getCookie('csrftoken')
            },
            body: JSON.stringify(data)
        })
        .then(response => response.json())
        .then(result => {
            console.log('Shift status updated successfully:', result);
        })
        .catch(error => {
            console.error('Error updating shift status:', error);
        });
    }

    // Function to retrieve the value of a cookie
    function getCookie(name) {
        const value = '; ' + document.cookie;
        const parts = value.split('; ' + name + '=');
        if (parts.length === 2) {
            return parts.pop().split(';').shift();
        }
    }
</script>

This is the view:

def update_shift_status(request, shift_id):
    if request.method == 'POST':
        status_id = request.POST.get('status_id')
        shift = get_object_or_404(Shift, id=shift_id)
        status = get_object_or_404(Status, id=status_id)  # Retrieve the Status object
        shift.status = status  # Assign the new status object
        shift.save()
        return JsonResponse({'message': 'Shift status updated successfully.'})
    else:
        return JsonResponse({'message': 'Invalid request.'}, status=400)

This is the url:

path('update_shift_status/<int:shift_id>/', views.update_shift_status, name='update_shift_status'),

Is that url in your root urls.py file or in an apps urls.py file?

What’s the line in the log after the “Not Found” message?

I do see one thing that’s obviously wrong.

You have:

Which means your post is JSON data and not form-based data.

However, your view has:

but there’s not going to be POST data.

See the docs at Request and response objects | Django documentation | Django

I modified my view to handle JSON data. Now it works. Thanks for pointing this out Ken!

Here is my view now:

def update_shift_status(request, shift_id):
    if request.method == 'POST':
        data = json.loads(request.body)
        status_id = data.get('status')

        if status_id is not None:
            try:
                shift = Shift.objects.get(id=shift_id)
                status = Status.objects.get(id=status_id)
                shift.status = status
                shift.save()
                return JsonResponse({'message': 'Shift status updated successfully.'})
            except (Shift.DoesNotExist, Status.DoesNotExist):
                return JsonResponse({'message': 'Shift or Status does not exist.'}, status=404)
        else:
            return JsonResponse({'message': 'Invalid request. Missing status ID.'}, status=400)
    else:
        return JsonResponse({'message': 'Invalid request. Must be a POST request.'}, status=400)