UpdateView in Django can't update

59 views Asked by At

I'm working on a Django app similar to some streaming platforms, as I am building a portfolio.

In the database management part (where I add, edit or delete films), I'm trying to use UpdateView (as I did on other projects) to update the films informations.

The link works, I go to the edit page where the form is populated with the already existing informations, but when I save after an edit, I got my message 'This film is already in the database', a message I created that should only appears when I add a film (with a modal and an API call). It's not even in the same view. I've tried everything I could, but I'm still stuck.

What I am trying to understand is what happens when I click on the save button. It looks like it redirects to the ManageFilmsView where it tries to create a new entrance to the database. Which is weird, as it is called UpdateView. Should I overwrite something in the UpdateView?

What can I try next?

Here is my views :

class ManageFilmsView(FormView, ListView):
    model = Film
    template_name = "manage-films.html"
    context_object_name = "films"
    form_class = AddFilmForm
    success_url = reverse_lazy("manage_films")

    def get_queryset(self):
        parameter = self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        return Film.objects.filter(title__startswith=parameter)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        letters = list(string.ascii_uppercase)
        context["letters"] = letters
        context["selected_letter"] = (
            self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        )
        return context

    def form_valid(self, form):
        search_title = form.cleaned_data["title"].replace(" ", "+")
        search_year = form.cleaned_data["year"]
        response = requests.get(
            f"http://www.omdbapi.com/?apikey={api_key}&t={search_title}&y={search_year}"
        )
        response.raise_for_status()
        film_data = response.json()

        if Film.objects.filter(title=film_data["Title"]).exists():
            messages.add_message(
                self.request,
                messages.INFO,
                f"This film is already present in the database.",
            )
        else:
            film = Film(
                title=film_data["Title"],
                year=film_data["Year"],
                genre=film_data["Genre"],
                country=film_data["Country"],
                director=film_data["Director"],
                actors=film_data["Actors"],
                runtime=film_data["Runtime"],
                poster=film_data["Poster"],
                plot=film_data["Plot"],
            )
            film.save()
            messages.add_message(
                self.request,
                messages.SUCCESS,
                f"{ film.title } successfully added to the database.",
            )
        return HttpResponseRedirect(self.get_success_url())

    def form_invalid(self, form):
        messages.add_message(self.request, messages.ERROR, "Something went wrong.")
        return HttpResponseRedirect(self.get_success_url())


class FilmsListView(ListView):
    model = Film
    context_object_name = "films"
    template_name = "manage-films-list.html"

    def get_queryset(self):
        parameter = self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        return Film.objects.filter(title__startswith=parameter)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        letters = list(string.ascii_uppercase)
        context["letters"] = letters
        context["selected_letter"] = (
            self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        )
        return context


class FilmEditView(UpdateView):
    model = Film
    fields = [
        "title",
        "year",
        "genre",
        "country",
        "director",
        "actors",
        "runtime",
        "poster",
        "trailer",
        "plot",
        "why",
    ]
    template_name = "edit-film.html"
    success_url = reverse_lazy("films_list")

Here is my urls

urlpatterns = [
    path("", ManageFilmsView.as_view(), {"letter": None}, name="manage_films"),
]

htmxpatterns = [
    path("<str:letter>", FilmsListView.as_view(), name="films_list"),
    path("edit/<int:pk>", FilmEditView.as_view(), name="edit_film"),
    path("delete/<int:pk>", DeleteFilmView.as_view(), name="delete_film"),
]

urlpatterns += htmxpatterns

Here is a shorter version of the edit-film.html :

{% load widget_tweaks %}

<h2 class="text-xl my-4 ml-10 p-4">Here are the details to edit the informations about the film "{{ film.title }}"</h2>
<form action="" action="" class="w-3/5 ml-10 flex flex-col" method="POST">  
    {% csrf_token %}  
    <div class="mb-4">
        <label class="mb-1 text-gray-100">{{ form.title.label|upper }}</label>
        {% render_field form.title class="bg-gray-50 border border-gray-300 text-gray-950 text-lg rounded-lg block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" %}
    </div>
    <div class="mb-4">
        <label class="mb-1 text-gray-100">{{ form.genre.label|upper }}</label>
        {% render_field form.genre class="bg-gray-50 border border-gray-300 text-gray-950 text-lg rounded-lg block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" %}
    </div>
    <button type="submit" value="Update" class="w-1/4 mt-2 mb-20 text-gray-100 bg-gray-900 hover:bg-gray-950 dark:bg-gray-600 dark:hover:bg-red-900 font-medium rounded-lg text-sm px-5 py-2.5 text-center place-items-center">SAVE</button>  
</form>
1

There are 1 answers

2
Voyageur Zen On

I used ChatGPT and after a long conversation, I changed my success_url to

success_url = reverse_lazy("films_list", kwargs={'letter': 'a'})

and then

success_url = reverse_lazy("manage_films")

and it works. I'm pretty sure I tried it, but the problem is gone.