Django html href query last object pass id to url tag

I have a button in my base template that needs to direct to a form to edit the last object in my model.

model:

class Cast(models.Model):
    id = models.AutoField(db_column='Id')
    startdate = models.DateTimeField(db_column='StartDate')
    enddate = models.DateTimeField(db_column='EndDate')

View:

def castend(request, id):
    context ={}
    obj = get_object_or_404(Cast, id = id)
    form = EndCastForm(request.POST or None, instance = obj)
    if request.method == 'POST':
        cast=Cast.objects.last()
        if form.is_valid():
            form.save()
            cast.refresh_from_db()
            cast.endcastcal()
            cast.save()
            return HttpResponseRedirect("/wwdb/casts/%i/castenddetail" % cast.pk)
    context["form"] = form
    return render(request, "wwdb/casts/castend.html", context)

url

    path('casts/<id>/castend/', views.castend, name="castend"),

base.py
This if/else statement determines if the enddate field is populated, the Start Cast button is passed to the view. Else the End Cast button is passed to the view. The End Cast button requires an id argument passed to the url.

    <div class="top-button-container stickey-top">
        {% if cast.objects.last.enddate %}
            <button type="button" class="btn btn-danger btn-lg btn-block">
                <a class="nav-link" href="{% url 'caststart' %}">Start Cast</a>
            </button>
        {% else %}
            <button type="button" class="btn btn-danger btn-lg btn-block">
                <a class="nav-link" href="{% url 'castend' %}">End Cast</a>
            </button>
        {% endif %}
    </div>

Start cast form
This form is how the user inputs most of the information for an entry. Once the form is submitted, the view redirects to the endcast form, using the cast object to pass the primary key to the url. I want the button in my base.py template to operate the was the HttpResponseRedirect functions in this view.

def caststart(request):
    context ={}
    form = StartCastForm(request.POST or None)
    if request.method == "POST":
        form = StartCastForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            castid=Cast.objects.last()
            return HttpResponseRedirect("%i/castend" % castid.pk)
    else:
        form = StartCastForm 
        if 'submitted' in request.GET:
            submitted = True
            return render(request, 'wwdb/casts/caststart.html', {'form':form, 'submitted':submitted, 'id':id})

    context['form']= form

    return render(request, "wwdb/casts/caststart.html", context)

How do I pass the pk of the last object in the cast model to the href url tag?

I have poked around online but have failed to come up with a solution for making this work in the template.

We can store the last object and then use that in the URL:

<div class="top-button-container stickey-top">
  {% with last=cast.objects.last %}
    {% if last.enddate %}
      <button type="button" class="btn btn-danger btn-lg btn-block"><a class="nav-link" href="{% url 'caststart' %}">Start Cast</a>
       </button>
    {% else %}
      <button type="button" class="btn btn-danger btn-lg btn-block">
                <a class="nav-link" href="{% url 'castend' last.pk %}">End Cast</a></button>
    {% endif %}
  {% endwith}
</div>

but this all look bad code design: making custom queries in the template and writing business logic in the template is often not a good idea.

How do I pass the pk of the last object in the cast model to the href url tag?

Yes, that’s the tricky bit. I would not do this that way. We can separate concerns here. We can make two views, one that redirects to the latest item, and one that then makes a form to edit an arbitrary id, so:

urlpatterns = [
    # …
    path('casts/end/', views.cast_end, name="cast-end"),
    path('casts/<int:id>/edit/', views.cast_edit, name="cast-edit"),
    # …
]

with cast_end a simple view:

from django.shortcuts import redirect


def cast_end(request):
    last = Cast.objects.latest('pk')
    return redirect('cast-edit', id=last.pk)

so the view itself will make a redirect to plug in the latest object.

Then the template is just:

<a href="{% url 'cast-end' %}">

Leave a Comment