Understanding Empty Strings Being Supplied to My Url when not specified

I am trying to click on a specific ingredient on my website which triggers an updateview. I get this 404 error which is included in my discord paste.

error message

The current path, ingredients/“/ingredient/update/3”, didn’t match any of these.

Why are empty strings involved? My urls nor my views call for this.

I have attempted to use chat GPT but it cannot explain it.

Based on the error message I need to supply a path that would give logic for
The current path, ingredients/“/ingredient/update/3”,

the url tied to this log is

    path('ingredient/update/<int:pk>',views.UpdateIngredientView.as_view(success_url = "/ingredients/"), name='ingredientupdate'),

with a view of

class UpdateIngredientView(UpdateView):  # I am thinking this is an UpdateView
    model = Ingredient
    template_name = "update_ingredient_view.html"
    fields = ["quantity", "price_per_unit"]

my url never called for empty strings but its being supplied. has anyone run into this issue before?

Using the URLconf defined in djangodelights.urls, Django tried these URL patterns, in this order:

[name='default']
admin/
finance/ [name='finance']
home/ [name='home']
ingredients/ [name='ingredients']
menu/ [name='menu']
purchases/ [name='purchases']
menu/add/ [name='menuadd']
ingredients/add/ [name='ingredientadd']
ingredient/update/<int:pk> [name='ingredientupdate']
recipe/add/ [name='recipeadd']
purchases/add/ [name='purchaseadd']
update/inventory/<int:pk>/ [name='updateinventory']
The current path, ingredients/“/ingredient/update/3”, didn’t match any of these.

views.py

from django.shortcuts import render
from django.urls import path, reverse_lazy
from .models import Ingredient, MenuItem, Purchases, RecipeRequirement
from django.views.generic import ListView
from django.core.exceptions import ImproperlyConfigured
# import one at the time write the view for it hook it up in urls.py check if it works than move on to the next one.
from .forms import (
    MenuAdditionForm,
    IngredientAdditionForm,
    UpdateIngredientForm,
    RecipeAdditionForm,
)  # link the views and forms togather on this line

# errors can come from importing on the wrong django.views
from django.views.generic.edit import CreateView, UpdateView
from django.http import HttpResponse

# Create your views here.


def finance(request):
    purchased_items = (
        Purchases.objects.all()
    )  # this grabs every row in the purchases table

    total_revenue = 0
    for item in purchased_items:
        total_revenue = (
            total_revenue + item.menu_order.price
        )  # this uses the price of each item to calculate the revenue

    print(str(total_revenue))
    total_cost = ingredient_cost_calculate()
    print(str(total_cost) + " this is the total cost calculation")

    total_profit = total_revenue - total_cost
    print(str(total_profit) + "total profit calculation amount")

    return render(
        request,
        "inventory/finance.html",
        {
            "total_revenue": total_revenue,
            "total_cost": total_cost,
            "total_profit": total_profit,
        },
    )
    # i want the price of the item and the cost of each item.
    # what holds this information? my ingredient model.
    # it holds the price per unit and the unit.


def ingredient_cost_calculate():
    # classes do not store information objects do.
    # i need the cost per ingredient multiplied by quantity used.
    # I need to than for loop over all of the ingredients in a recipe and than apply the cost per ingredient function or
    # the same mathematical operation.
    # classes do not have the data, the objects do.
    # when the customer purchases something an entry is made in the purchases table.
    # Purchases.objects.all() grabs all of the Purchases data and puts it in a list.
    purchases_objects = Purchases.objects.all()
    # I need to find all of the ingredients per order. How do I get one order to find the ingredients on.
    # I need to use a for loop to access each purchase.
    menu_order_cost = 0
    for purchase in purchases_objects:
        menu_item_object = purchase.menu_order
        # recipe requirements is a list of data
        recipe_requirements = RecipeRequirement.objects.filter(recipe=menu_item_object)
        # we iterate over that list with a for loop and access the iteration variable quantity fields.

        for requirement in recipe_requirements:
            cost_per_ingredient = (
                requirement.quantity * requirement.ingredient.price_per_unit
            )
            menu_order_cost = menu_order_cost + cost_per_ingredient
    return menu_order_cost

    # the purchases are listed by names they do hold the ingredient data for each indvidual order.


def home(request):
    return render(request, "inventory/home.html")


class MenuView(ListView):
    # when we specify the model being used for the template its almost as if we import or give access
    # to the html template the class data for us to use for loops and django code on.
    model = MenuItem
    template_name = "inventory/menu.html"


class PurchaseView(ListView):
    model = Purchases
    template_name = "inventory/purchases.html"


class IngredientsView(ListView):
    model = Ingredient
    template_name = "inventory/ingredients.html"


class IngredientsListUpdateView(ListView):
    model = Ingredient
    template_name = "inventory/ingredients_update.html"


class MenuAdditionView(CreateView):
    model = MenuItem
    template_name = "inventory/form_template.html"
    form_class = MenuAdditionForm
    success_url = "/menu/"
    
    # fields = ["name", "description", "price"]

class IngredientAdditionView(CreateView):
    model = Ingredient
    template_name = "inventory/form_template.html"
    form_class = IngredientAdditionForm


class UpdateIngredientView(UpdateView):  # I am thinking this is an UpdateView
    model = Ingredient
    template_name = "update_ingredient_view.html"
    fields = ["quantity", "price_per_unit"]

    # success_url field attribute and reverse_lazy are used with updateview. upon successful completion of the viewd django
    # will route the user to the url with the name pattern of ingredientupdate

    def get_success_url(self):
        """Return the URL to redirect to after processing a valid form."""
        if not self.success_url:
            raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.")
        return str(self.success_url)  # success_url may be lazy  

    # fields = we need to input the fields of the columns that the provided model has.
    # per ken I need the get_success_url method.


class RecipeRequirementAdditionView(CreateView):
    model = RecipeRequirement
    template_name = "inventory/form_template.html"
    fields = ["ingredient", "recipe", "quantity"]


class PurchaseAdditionView(CreateView):
    model = Purchases
    template_name = "inventory/form_template.html"
    fields = ["menu_order", "timestamp"]


# update view will require a <pk> or slug where I specify what I need to update.
# check out the codecademy section.
# https://www.codecademy.com/paths/build-python-web-apps-with-django/tracks/views-in-django/modules/django-writing-more-views/lessons/django-views/exercises/using-primary-keys-in-urls


# create a view based on the forms made.
# create a path to urls.py


urls.py
# urls.py 
from django.contrib import admin
from django.urls import path, include
# from inventory.views import finance, home, IngredientsView, MenuView, PurchaseView
from inventory import views # with every view imported you need to specify views.viewname as seen in this file in the code below
from django.views.generic.base import TemplateView
from django.http import HttpResponse

urlpatterns = [
    
    path('', views.home, name='default'), # users don't need to see the rocket page anyway. they need to see the home page.
    path('admin/', admin.site.urls),
    path('finance/', views.finance, name='finance'),
    path('home/', views.home, name='home'), #I am attempting to connect the home_view function with the views function.
    path('ingredients/', views.IngredientsView.as_view(), name='ingredients'),
    path('menu/', views.MenuView.as_view(), name='menu'),
    path('purchases/', views.PurchaseView.as_view(), name='purchases'), 
    path('menu/add/',views.MenuAdditionView.as_view(success_url = "/menu/"), name="menuadd"),
    path('ingredients/add/', views.IngredientAdditionView.as_view(success_url = "/ingredients/"), name='ingredientadd'), # if class based view it requires an as_view
    path('ingredient/update/<int:pk>', views.UpdateIngredientView.as_view(success_url = "/ingredients/"), name='ingredientupdate'),
    path('recipe/add/', views.RecipeRequirementAdditionView.as_view(success_url = "/menu/"), name='recipeadd'),
    path('purchases/add/', views.PurchaseAdditionView.as_view(success_url = "/purchases/"), name = 'purchaseadd'),
    path('update/inventory/<int:pk>/', views.IngredientsListUpdateView.as_view(), name='updateinventory'), # update view so the view had to be edited.}
    # cannot have conflicting path names or matching names
    # finance is not a classed based view therefore i do not need an as_view
    # error message views.finance() type error means I a. calling the fucntion wrong or I am not supposed to be calling it.
    # It needs to know what it is updating. 
    ]
    
update_ingredient_view.html
{% extends "inventory/base.html" %}
{% block content %}
<form method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="Submit"/>
</form>
{% url 'ingredientupdate' pk=object.id%}
{% endblock %}

We need to see the view and template you are on when the error is generated, not the view you’re trying to get to.

@KenWhitesell

okay from now on I need to break the code down into respective files and not one field because it is more readable. I am trying to get better.

per the error message:
Request URL: http://127.0.0.1:8000/ingredients/“/ingredient/update/3”

it looks like its ingredient/update view that is being used.

path("ingredient/update/<int:pk>",views.UpdateIngredientView.as_view(success_url="/ingredients/"),name="ingredientupdate"),

views.py

class UpdateIngredientView(UpdateView):  # I am thinking this is an UpdateView
    model = Ingredient
    template_name = "update_ingredient_view.html"
    fields = ["quantity", "price_per_unit"]

    # success_url field attribute and reverse_lazy are used with updateview. upon successful completion of the viewd django
    # will route the user to the url with the name pattern of ingredientupdate

    def get_success_url(self):
        """Return the URL to redirect to after processing a valid form."""
        if not self.success_url:
            raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.")
        return str(self.success_url)  # success_url may be lazy  

update_ingredient_view.html

{% extends "inventory/base.html" %}
{% block content %}
<form method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="Submit"/>
</form>
{% url 'ingredientupdate' pk=object.id%}
{% endblock %}

as for the webpage that I am on when the url is clicked it is the ingredients page

http://127.0.0.1:8000/ingredients/

that view is

    path("ingredients/", views.IngredientsView.as_view(), name="ingredients"),

that template is:

ingredients.html

{% extends 'inventory/base.html' %} 

{% block content %}
{% load static %}
<link rel = "stylesheet" href="{% static 'inventory/style.css' %}">
<h1> Welcome to the ingredients page!</h1>

<table>
    <thead>
        <tr>
            <th>Ingredient Name</th>
            <th>Quantity</th>
            <th>Unit Type</th>
            <th>Price Per Unit</th>
        </tr>
    </thead>
    <!-- context is a list of objects from a listview 
    object list is is inside of context and its a list of items.
    this for loop says itemize each item in object list and iterates over item.name
    the model that listview is using has attributes such as item.name and so on. 

    listview has a built in system to query the database for the model specified


    model specifies what data exists in the database 
    there are views of different types and they views take data from the model in their respective different ways.
    in other words the view decides what is taken from the database and what functions it can operate with.
    context is the mechanism that the view uses to talk to the template. 
    The template can only grab things from the context. the view CANNOT talk to the model.--> 
    {% for item in object_list %}
    <tr><td>
        {{ item.name }} 
        <a target=“_blank” href=“{% url "ingredientupdate" item.pk %}”>{{ item.name }}</a>
        </td> 
        <td>{{ item.quantity}}</td> 
        <td>{{ item.unit }}</td> 
        <td>{{ item.price_per_unit }}</td>
    </tr>
    {% endfor %}
</table>
{% endblock %}

I am trying to click on a specific ingredient on my website which triggers an updateview. I get this 404 error which is included in my discord paste.

error message
The current path, ingredients/“/ingredient/update/3”, didn’t match any of these.

Why are empty strings involved? My urls nor my views call for this.

I have attempted to use chat GPT but it cannot explain it.

Can anyone assist?

What have I tried and what am I expecting?

After rubber duck debugging I discovered:
That the current path, ingredients/”/ingredient/update/3 didn’t match any of my urls. I am not trying to get my hyperlink to access that path. Its inputting empty strings.
Looking at the link it seems to be accessing the ingredients page like I told it to when I first clicked on that link from the home page. From there when I click on the ingredient itself the hyperlink route breaks the code. I think the breakdown output the webpage gives is a clue.
The current path, ingredients/“/ingredient/update/3”, didn’t match any of these.
I never asked for empty strings. The update comes from my update view being called most likely.
My updateingredientview uses update_ingredient_view.html and the url

path(“ingredient/update/int:pk”,views.UpdateIngredientView.as_view(success_url=“/ingredients/”),name=“ingredientupdate”),

Perhaps this has something to do with targeting one ingredient instead of all of the object ingredients.

Chat GPT it suggested: It suggested trying to update my template with a pk= some integer manually. I do not think this will work as I am trying to be able to update multiple ingredients at once.

After I checked the Django documentation I found:
The django documentation says that when a url is is called in order it will activate the first matching url and call the view which activates the template rendering. Is it possible that by calling this function I have created an empty string in the url somehow?

Upon further reading the documentation it talks about capturing values my own url shown below captures the int:pk value. This is targeting the primary keys of the ingredients table. Cane sugar has a different primary key than beef. I am wondering if even if I successfully fix the empty space issue if it will grab it.
path(“ingredient/update/int:pk”,views.UpdateIngredientView.as_view(success_url=“/ingredients/”),name=“ingredientupdate”),

I checked the django forum for questions: there are none like this on record after searching.
I checked Stack Overflow and found no articles related to this issue.

Is there anyone who can give any advice?

error message:
https://paste.pythondiscord.com/GWXQ

When I click on the pathway

The current path, ingredients/“/ingredient/update/3”, didn’t match any of these.

I needed to use single quotes in my django templates from now on. By having ’ and " quotes I have django start reading links that are not there.

Per GinFuyous answer on october 17th 2023

  1. It caused link to be rendered like href=“/ingredient/update/3“ and browser didn’t recognize first symbol as quote and thought it’s part of link. And since first symbol in link is not a / it thought it’s a relative ling so it concantinated it with current url making it to what you’ve seen /ingredients/“/ingredient/update/3”