Django - Can't get the specific primary key (id) for an object in a list of objects

Viewed 154

I am trying to get the specific pk of the selected object when the user accepts a delivery. My problem is that I'm getting only the first object's pk in the list every time. I want to get the pk of the selected object.

views:

@login_required(login_url="/signin/?next=/driver/")
def deliveries_available_page(request):

    deliveries = Delivery.objects.filter(
        status_of_delivery__in=[Delivery.DELIVERY_POSTED]
    )
    
    #When driver accept delivery then status of delivery changes to delivering
    if request.method == 'POST':
        delivery = get_object_or_404(Delivery, pk=request.POST.get('receipt_number'))
        if delivery:
            delivery.status_of_delivery = Delivery.DELIVERY_DELIVERING
            delivery.driver = request.user.driver
            messages.success(request, 'Delivery Accepted')
            delivery.save()
    
        return redirect(reverse('driver:deliveries_available'))
    return render(request, 'driver/deliveries_available.html', {
        "GOOGLE_API_MAP": settings.GOOGLE_API_MAP,
        "del": deliveries
    })

HTML:

<div class="d-flex flex-column h-100" style="padding-bottom: 50px">
    <div id="map"></div>
    {% if del %}
    {% for d in del %}
    <div class="card" id="delivery-popup">
        <div class="card-body p-2">
            <div class="details">
                <div class="p-2">
                    <strong id="address"></strong>
                    <div>
                        <strong id="show-info"></strong>
                    </div>
                    <div>
                        <strong id="show-distance"></strong>
                        <strong id="show-duration"></strong>
                    </div>
                    <div>
                        <strong id="show-price"></strong>
                        <strong id="show-id"></strong>
                    </div>


                    <div>
                        <form method="POST">
                            {% csrf_token %}
                            <button type="submit" class="btn btn-primary"        name="accept">Accept</button>
                            <input type="hidden" value="{{ d.receipt_number }}" name="receipt_number">
                        </form>
                    </div>
                    
  
                    {% if messages %}
                    {% for m in messages %}
                    {% if m.tags %}
                    <script>alert("{{ m }}")</script>
                    {% endif %}
                    {% endfor %}
                    {% endif %}
                </div>
            </div>
        </div>
    </div>
    {% endfor %}
    {% endif %}

When i click on the address the pk stays the same

I need the specific pk so when user accept delivery, then the right delivery is accepted and removed from the map. Any help would be appreciated. Thanks.

I can get the specific pk by creating new url and passing it in the url but i want user to accept delivery on the map page.

script added to html

<script>
//Google map and using api to display deliveries on map and click event to show delivery details
function initMap() {
    const map = new google.maps.Map(document.getElementById("map"), {
        center: { lat: 53.350140, lng: -6.266155 },
        zoom: 13,
    });

    fetch("{% url 'driver:available_deliveries' %}").then(response => response.json()).then(json => {
        console.log(json);

        for (let d = 0; d < json.deliveries.length; d++) {
            const delivery = json.deliveries[d];
            const position = { lat: delivery.delivery_address_latitude, lng: delivery.delivery_address_longitude };
            const show_on_map = new google.maps.Marker
                ({
                    position,
                    map,
                });

            new google.maps.InfoWindow({
                content: "<small><strong>" + delivery.address + "<medium><br>€" + delivery.price
            }).open(map, show_on_map);

            show_on_map.addListener("click", () => {
                PopUpDelivery(delivery);
            })
        }
    })
}

function PopUpDelivery(delivery) {
    $("#delivery-popup").css("display", "block");
    $("#address").html(delivery.address);
    $("#show-distance").html(delivery.distance + " Km");
    $("#show-duration").html(delivery.duration + " Mins");
    $("#show-price").html("€ " + delivery.price);
    $("#show-info").html("Info : " + delivery.information);
    $("#show-id").html("Pk : " + delivery.receipt_number)
}
2 Answers

Solved:

Got the specific pk, when i click on a delivery it gets the right pk, code below if anyone has the same problem:

script

function PopUpDelivery(delivery) {
    $("#delivery-popup").css("display", "block");
    $("#address").html(delivery.address);
    $("#show-distance").html(delivery.distance + " Km");
    $("#show-duration").html(delivery.duration + " Mins");
    $("#show-price").html("€ " + delivery.price);
    $("#show-info").html("Info : " + delivery.information);
    $("#show-id").html("Pk : " + delivery.receipt_number);
    
    var input_tag = getTag('getpk');
    input_tag.value = delivery.receipt_number;
}
function getTag(id){
    return document.getElementById(id);
}

html

<button type="submit" class="btn btn-primary" name="accept">Accept</button>
                        <input type="hidden" id="getpk" value="" name="receipt_number">

Keep id unique in html document

The id in an HTML document must be unique within each page source:

The id global attribute defines an identifier (ID) which must be unique in the whole document. Its purpose is to identify the element when linking (using a fragment identifier), scripting, or styling (with CSS).

What I think may have occurred is that since you have many cards in each page, all with the same id's, you were just getting the first one. While your solution works, I think it might be better to give each id a unique value, which you can do simply by appending the receipt_number, or any unique field to the id names. With this, you may not need the function getTag. Here is what I mean:

html

<div class="d-flex flex-column h-100" style="padding-bottom: 50px">
    <div id="map"></div>
    {% if del %}
    {% for d in del %}
    <div class="card" id="delivery-popup{{ d.receipt_number }}">
        <div class="card-body p-2">
            <div class="details">
                <div class="p-2">
                    <strong id="address{{ d.receipt_number }}"></strong>
                    <div>
                        <strong id="show-info{{ d.receipt_number }}"></strong>
                    </div>
                    <div>
                        <strong id="show-distance{{ d.receipt_number }}"></strong>
                        <strong id="show-duration{{ d.receipt_number }}"></strong>
                    </div>
                    <div>
                        <strong id="show-price{{ d.receipt_number }}"></strong>
                        <strong id="show-id{{ d.receipt_number }}"></strong>
                    </div>


                    <div>
                        <form method="POST">
                            {% csrf_token %}
                            <button type="submit" class="btn btn-primary" name="accept">Accept</button>
                            <input type="hidden" value="{{ d.receipt_number }}" name="receipt_number">
                        </form>
                    </div>
                    
  
                    {% if messages %}
                    {% for m in messages %}
                    {% if m.tags %}
                    <script>alert("{{ m }}")</script>
                    {% endif %}
                    {% endfor %}
                    {% endif %}
                </div>
            </div>
        </div>
    </div>
    {% endfor %}
    {% endif %}

script

<script>
//Google map and using api to display deliveries on map and click event to show delivery details
function initMap() {
    const map = new google.maps.Map(document.getElementById("map"), {
        center: { lat: 53.350140, lng: -6.266155 },
        zoom: 13,
    });

    fetch("{% url 'driver:available_deliveries' %}").then(response => response.json()).then(json => {
        console.log(json);

        for (let d = 0; d < json.deliveries.length; d++) {
            const delivery = json.deliveries[d];
            const position = { lat: delivery.delivery_address_latitude, lng: delivery.delivery_address_longitude };
            const show_on_map = new google.maps.Marker
                ({
                    position,
                    map,
                });

            new google.maps.InfoWindow({
                content: "<small><strong>" + delivery.address + "<medium><br>€" + delivery.price
            }).open(map, show_on_map);

            show_on_map.addListener("click", () => {
                PopUpDelivery(delivery);
            })
        }
    })
}

function PopUpDelivery(delivery) {
    let pk = delivery.receipt_number
    $("#delivery-popup"+pk).css("display", "block");
    $("#address"+pk).html(delivery.address);
    $("#show-distance"+pk).html(delivery.distance + " Km");
    $("#show-duration"+pk).html(delivery.duration + " Mins");
    $("#show-price"+pk).html("€ " + delivery.price);
    $("#show-info"+pk).html("Info : " + delivery.information);
    $("#show-id"+pk).html("Pk : " + delivery.receipt_number)
}
Related