# Preventing errors from reverse URL for javascript

**URL:** <https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995>\
**Category:** Using Django\
**Created:** [May 21, 2021, 2:49pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995 "2021-05-21T14:49:22Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![logikonabstractions](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/logikonabstractions/32/4066_2.png) [@logikonabstractions](https://forum.djangoproject.com/u/logikonabstractions)\
**Post date:** [May 21, 2021, 2:49pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995/1 "2021-05-21T14:49:22Z")

</div>

Hey,

Unsure how to phrase this but here’s my use case.

I’m making ajax calls based on some events in a table (row click/dbl-clicked). In order to avoid hard-coding URLs, I’m using a data-url attribute in my templates, like so:

```
      <tbody id="details" data-url="{% url 'pickings:details' %}">

```

For instance in this case, the body of the table is initially empty. When I want to make an ajax query to populate it, jquery fetches the data-url attr of the #details element and appends to it the html rendered by the server. Works well.

However, there are instances where the reverse URL expects say an int:pk, like so:

```
    <table class="table table-bordered" id="table_list" width="100%" cellspacing="0" data-url="{% url 'pickings:detail_product' %}">

```

With the corresponding urls.py:

```
path('product/<int:pk>/', views.PickWarehouseDetailedView.as_view(), {"section": "product"}, name='detail_product', ),

```

Obviously, when rendering my template, django complains that it cannot find a reverse for  
data-url="{% url ‘pickings:detail\_product’ %}", since I don’t know which one it will be at that time.

My current workaround is to provide a dummy one & strip it when I make the ajax call (e.g. a row has been double-clicked, and there’s an associated product pk). However I would ideally like to:

- Keep using the reserve URL the way I do to tell my jquery requests where to go
- avoid messing around with stripping strings from URL
- so more or less “silence” the Django error about not finding a reverse%

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [May 21, 2021, 2:56pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995/2 "2021-05-21T14:56:56Z")

</div>

We render the template with a pk of 0, then in the JavaScript, replace the zero in ‘/0/’ with the pk from the item selected.  
(We have a slightly different solution when the URL contains more than one variable needing to be replaced, but the idea is the same.)

---

<div class="post-metadata">

**Author:** ![logikonabstractions](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/logikonabstractions/32/4066_2.png) [@logikonabstractions](https://forum.djangoproject.com/u/logikonabstractions)\
**Post date:** [May 21, 2021, 3:02pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995/3 "2021-05-21T15:02:32Z")

</div>

Okay, if Ken says that’s the way he does it, then there’s no other options. I guess in a way it wouldn’t make sense, like Django is warning me it cannot find an reverse in my template, and in general it is indeed something I’d want to know, so shutting down the warning might not be so well advised.

It still does feel a little hacky to me.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [May 21, 2021, 4:06pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995/4 "2021-05-21T16:06:16Z")

</div>

> [@logikonabstractions](#):
>
> Okay, if Ken says that’s the way he does it, then there’s no other options.

Not really the intent of my reply, and yes, I probably should have put more thought into it. (That’s what I get when I fire off a quick reply on my phone.)  
There are other options, I even hinted at one when I made my reference to having multiple-replaced parameters.

Five other viable solutions are:

- Match the url up to where the variables begin. Then, instead of relying upon Django to process the path components of the variables area, handle it yourself in your code. (There is nothing forcing you to have Django process a complete URL.)
- Add the variables as GET parameters on the end of the URL
- Create a separate “dummy” URL entry that doesn’t have the parameters - use that for the reverse function. Then instead of replacing URL components, you’re concatenating on to the end of the URL.
- Render the complete URL as a data element for each selectable item, so that when the item is clicked, you use the URL from that item.
- Define some API [endpoints as fixed URLs, and not subject to change](https://www.w3.org/Provider/Style/URI), making it unnecessary to use reverse.

Then, becoming absurd and not being presented seriously:

- Create a URL-generation endpoint. Write a view that takes a URL name and appropriate parameters, return the reversed URL.

I’m fairly sure that at one time or another I’ve implemented or worked on a system using most of these. (But definitely not the last one.)  
My opinion is that they all feel “hacky” in some way - and I think that comes from having to effectively split the processing of the URLs between both sides of the communications channel. (Django doesn’t know which item is going to be selected, and the JavaScript doesn’t have the information to be able to do its own `reverse` implementation.)

We settled on the original idea because, _for us_ it ended up being the “easiest and most understandable solution.”

---

<div class="post-metadata">

**Author:** ![logikonabstractions](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/logikonabstractions/32/4066_2.png) [@logikonabstractions](https://forum.djangoproject.com/u/logikonabstractions)\
**Post date:** [May 21, 2021, 4:25pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995/5 "2021-05-21T16:25:08Z")

</div>

Oh, it wasn’t meant as a criticism or anything wrt to your initial (indeed short) reply. More a mark of respect actually - if you haven’t found an obviously better, less “hacky” way to do this, then it probably means there isn’t. Or just at least that there’s little point in my investing much time in improving the approach.

Also somewhat comforting to know that using reverse url in this way (e.g. in html attribute in my template) to tell my JS code where to call is a legitimate way to do this. I was 95% it was fine, but as I don’t have ton of experience, I try to keep a healthy skepticism about those, let’s say, “non built-in” features I use/develop.

==============

Regarding the alternatives you elaborated - does show there is more to it than I initially thought. Just for the fun of thinking out loud, and perhaps others coming accross this will enjoy the thoughts…

Alternatives that involve modifying the url itself feel wrong. I think that a good url that clearly shows the user “where” he is in the application, and also that is bookmarkable (e.g. products/details/2321312/) is what I need to aim for as a dev. I find I’m not willing to compromise on that in order to achieve some goals that purely have to do with my job as a dev, behind the curtains.

I had considered the one about having a “dummy” endpoint w/o arguments. It felt _more_ hacky to me - the view needs an argument to mean anything. Thus I feel that whatever happens, I should provide it with one.

And yes, endpoints _should_ be fixed. But alas, I’m developing this agile-style, and thus I can’t guarantee that I’ll have the foresight to makes this robust & well-thought enough so that they won’t change. Even setting longer-term aside, while prototyping things, it’s nice to be fairly confident that by changing some url structure, I’m not breaking some ajax calls that may be hard to test for and go under the radar for a while, until later when I won’t be obvious to me why it’s broken… Which is actually the main reason I decided to figure out a way to use reverses in the template for this in the first place…

I think you’re very right in saying the issue arose from the “split” of the url processing. The way I see it at this point, is that the “split” occurs because I’m adding another component to the system (javascript/ajax calls). Therefore, if something’s got to give, it’s logical that the “added” component that “creates” the problem should be one which side I’ll work out the solutions (hacks).

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [May 21, 2021, 4:54pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995/6 "2021-05-21T16:54:49Z")

</div>

Still just thinking aloud here - I do enjoy the mental exercise - but I’d like to add some comments to your thoughts:

> [@logikonabstractions](#):
>
> Alternatives that involve modifying the url itself feel wrong. I think that a good url that clearly shows the user “where” he is in the application, and also that is bookmarkable (e.g. products/details/2321312/) is what I need to aim for as a dev.

I’m not understanding this comment. You’re not modifying any “seen” url. The URL you are referencing or being directed to is the final URL and can be bookmarked. The URL fragment and the work being done to it is never seen by the user.

> [@logikonabstractions](#):
>
> I had considered the one about having a “dummy” endpoint w/o arguments. It felt _more_ hacky to me - the view needs an argument to mean anything.

In the situation where this was used, the dummy URL was defined to use a view returning a 404. It could never be used directly as an endpoint. It only existed as a url entry in the urls.py file, to be used as the name for a call to reverse.

> [@logikonabstractions](#):
>
> And yes, endpoints _should_ be fixed.

Another project worked on - actually a conversion of a flask-project - all external APIs were prefixed by /a/ - it was a completely separate URL structure from the rest of the application. It’s a single urls.py file that maps a full URL to a view.  
Those URLs are etched in stone and are not to be modified regardless of any other changes made to the application. (You can have more than one URL referring to the same view.) They were defined 5 years ago (6 now?) and are still valid. (Ok, so being honest, it’s only about a dozen URLs for which this was done. It’s not that much of a maintenance issue.)

---

<div class="post-metadata">

**Author:** ![logikonabstractions](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/logikonabstractions/32/4066_2.png) [@logikonabstractions](https://forum.djangoproject.com/u/logikonabstractions)\
**Post date:** [May 25, 2021, 9:34pm UTC](https://forum.djangoproject.com/t/preventing-errors-from-reverse-url-for-javascript/7995/7 "2021-05-25T21:34:20Z")

</div>

> > [@logikonabstractions](#):
> >
> > Alternatives that involve modifying the url itself feel wrong. I think that a good url that clearly shows the user “where” he is in the application, and also that is bookmarkable (e.g. products/details/2321312/) is what I need to aim for as a dev.
> 
> I’m not understanding this comment. You’re not modifying any “seen” url. The URL you are referencing or being directed to is the final URL and can be bookmarked. The URL fragment and the work being done to it is never seen by the user.

My bad actually - I had always just sort of assumed that putting the variable within the GET parameters would means that `products/details/2321312/` would become `products/details/`.

Thanks for the additional uses cases/experiences. I for one definitely can learn from that - helps broaden perspective and just be better able to think outside the box in the futur.
