learyjk
learyjk

Reputation: 739

Remove an item and reverse URL lookup at same time

I am building a calendar application in Django. I have implemented functionality to let a user add/remove Highlights to his/her week. Since the highlights are rendered on each individual week's page, I want to return the user to that page after deleting the highlight from the database. However, my remove_note() method takes 2 parameters (request, note_id). In the method, I query the database for the week associated with that note so that I can redirect the user to the week_view of the corresponding week_number. My thought - is there a way to pass note_id and week_number from the week_view.html to reduce database calls? I tried but couldn't quite get there myself. Thank You!

views.py

from django.shortcuts import render, get_object_or_404, redirect
from week.models import Week, Note
from week.forms import NoteForm


def index(request):

    week_list = Week.objects.filter(user_id=request.user.id).order_by('week_number')

    context = {
        'week_list': week_list,
        'cal_width': range(52),
    }
    return render(request, 'cal/index.html', context)


def week_view(request, week_number):
    if request.method == "POST":
        week = get_object_or_404(Week, week_number=week_number, user_id=request.user.id)
        form = NoteForm(request.POST)
        if form.is_valid():
            form = form.cleaned_data
            new_note = Note(text=form['text'], week=week)
            new_note.save()

        context = {
            'week': week,
            'form': NoteForm(),
            'notes': week.note_set.all(),
        }
        return render(request, 'cal/week_view.html', context)
    else:
        week = get_object_or_404(Week, week_number=week_number, user_id=request.user.id)

        context = {
            'week': week,
            'form': NoteForm(),
            'notes': week.note_set.all(),
        }
        return render(request, 'cal/week_view.html', context)


def remove_note(request, note_id):
    note = Note.objects.get(id=note_id)
    week = Week.objects.get(id=note.week.id, user_id=request.user.id)
    note.delete()
    return redirect('week_view', week_number=week.week_number)

week_view.html

{% extends 'base.html' %}

{% block content %}
<p><a href="{% url 'index' %}">Back to Calendar</a></p>

You are viewing week number {{week.week_number}} of your life.
<p>
The week of: {{week.date}}

<p>
    <form method="POST" action="{% url 'week_view' week.week_number %}">
    {% csrf_token %}
    {{ form }}
    <input type="Submit" value="Add Highlight">
    </form>



Highlights:
{% for note in notes %}
    <li>{{note}} <a href="{% url 'remove_note' note_id=note.id %}">Delete</a> </li>
{% endfor %}

{% endblock %}

urls.py

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:week_number>/', views.week_view, name='week_view'),
    path('remove_note/<int:note_id>/', views.remove_note, name='remove_note'),
]

models.py

from django.db import models
from datetime import date, timedelta


class Week(models.Model):
    id = models.AutoField(primary_key=True)
    user_id = models.IntegerField()
    week_number = models.IntegerField()
    text = models.TextField(blank=True)
    date = models.DateField(null=True)

    def __str__(self):
        return "O"

    @property
    def is_past(self):
        return self.date <= date.today()

    @property
    def is_current_week(self):
        return self.date <= date.today() and self.date > (date.today() - timedelta(7))


class Note(models.Model):
    text = models.CharField(max_length=255, blank=True)
    week = models.ForeignKey(Week, on_delete=models.CASCADE, default=1, null=False)

    def __str__(self):
        return self.text

Upvotes: 1

Views: 119

Answers (1)

Iain Shelvington
Iain Shelvington

Reputation: 32274

You can add an additional parameter to the remove_note url and view

path('remove_note/<int:note_id>/<int:week_number>/', views.remove_note, name='remove_note')

def remove_note(request, note_id, week_number):
    note = Note.objects.get(id=note_id).delete()
    return redirect('week_view', week_number=week_number)

Then pass week_number in the url tag

{% url 'remove_note' note_id=note.id week_number=week.week_number %}

Upvotes: 1

Related Questions