\n\n```\n\nExternal JS:\n```javascript\nconst url = window.ADD_TO_CART_URL;\n```\n\nBoth approaches remove template tags from static files and keep your JS static and cacheable. See common community discussion about passing the CSRF token or URLs from templates to JS: https://stackoverflow.com/questions/23349883/how-to-pass-csrf-token-to-javascript-file-in-django and https://stackoverflow.com/questions/22688032/django-ajax-request-from-external-javascript-file.\n\n---\n\n## Django Static Files: correct loading & order {#django-static-files}\n\nIf your external file never runs the most common causes are: wrong static path, the browser not loading the file, or wrong script order (jQuery loaded after your code). Quick checks and fixes:\n\n- Use Django's static tag and make sure `django.contrib.staticfiles` is in INSTALLED_APPS:\n ```django\n {% load static %}\n \n \n ```\n- Put static script includes at the end of the body or use `defer` so the DOM is ready when the script runs.\n- In development, confirm the script file returns 200 in DevTools Network. In production, run `collectstatic` and configure your webserver to serve static files; see Django docs on static files: https://docs.djangoproject.com/en/4.1/howto/static-files/.\n- Clear browser cache or use hashed filenames (ManifestStaticFilesStorage) to avoid stale cached JS.\n\nIf jQuery is not defined when your external code runs you'll see console errors like `Uncaught ReferenceError: $ is not defined`. Fix the include order (jQuery first) or use an AMD/bundler/defer approach.\n\n---\n\n## Django CSRF in external JavaScript {#django-csrf}\n\nYou already read the CSRF token from a data attribute — that's valid. But common pitfalls:\n\n- Putting `{% csrf_token %}` inside a script tag incorrectly can produce a JS syntax error (don't output raw token text without quoting).\n- If you try to read the CSRF token from cookie but you enabled `CSRF_COOKIE_HTTPONLY = True`, JavaScript won't be able to read it.\n- External JS must set the X-CSRFToken header (or include the token in POST data) for non-safe requests.\n\nRecommended safe patterns\n\n1) Meta tag or data attribute + header per-request:\nTemplate:\n```html\n\n```\nExternal JS:\n```javascript\nconst csrftoken = document.querySelector('meta[name=\"csrf-token\"]').getAttribute('content');\n\n$.ajax({\n type: 'POST',\n url: url,\n data: { productId },\n headers: { 'X-CSRFToken': csrftoken }\n});\n```\n\n2) Read from cookie (vanilla getCookie) and set up $.ajax globally. Example getCookie from a community gist: https://gist.github.com/sirodoht/fb7a6e98d33fc460d4f1eadaff486e7b\n\n```javascript\nfunction getCookie(name) {\n let cookieValue = null;\n if (document.cookie && document.cookie !== '') {\n const cookies = document.cookie.split(';');\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n if (cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n}\nconst csrftoken = getCookie('csrftoken');\n\n$.ajaxSetup({\n beforeSend: function(xhr, settings) {\n if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {\n xhr.setRequestHeader(\"X-CSRFToken\", csrftoken);\n }\n }\n});\n```\n\nDjango documents this header technique here: https://docs.djangoproject.com/en/5.2/howto/csrf/.\n\n---\n\n## Common runtime errors and debugging checklist {#debugging-checklist}\n\nWhen your inline version works but external doesn't, follow this checklist — they solve 90% of cases:\n\n- Open DevTools → Console: any errors? `Uncaught ReferenceError: $ is not defined`, `TypeError: Cannot read property 'addEventListener' of null`, or a SyntaxError will stop execution.\n- Network tab: is the external .js fetched (200)? Is the AJAX request being sent at all? If yes, what is the request URL and status code (403 = CSRF failed, 404 = wrong URL)?\n- Confirm script order: jQuery first, then your script. If you see `$ is not defined` fix order.\n- Confirm your template tags are not inside the external .js. If you see literal `{% url ... %}` in the JS or in the request URL, move the tag into the HTML (data- attribute or inline `window.` var).\n- Check that your selector finds the element: `document.querySelector('.add-to-cart')` can be null if the element isn't present. Use event delegation as needed: `$(document).on('click', '.add-to-cart', handler)`.\n- Check CSRF: if server returns 403, inspect request headers to see if `X-CSRFToken` was sent; ensure you're reading the correct token source (cookie vs meta vs data attribute).\n- Spelling options: jQuery uses `dataType` (capital T). A wrong option name can be ignored; it won't usually break the request but is worth checking.\n- If you use HTMX or replace DOM segments dynamically, scripts may need re-initialization — prefer event delegation.\n\nIf you're unsure, paste the external JS URL into the browser to inspect the delivered file. That quickly shows whether a template tag remains unrendered or whether the file is stale/cached.\n\n---\n\n## Quick fixes and recommended code samples {#quick-fixes}\n\n1) Minimal and robust — data-attribute + jQuery post:\nTemplate:\n```html\n\n```\nExternal JS:\n```javascript\n$(function(){\n $(document).on('click', '.add-to-cart', function(){\n const btn = this;\n const url = btn.dataset.url;\n const productId = btn.dataset.itemId;\n const csrftoken = btn.dataset.csrf; // or from meta/cookie\n $.ajax({\n type: 'POST',\n url: url,\n data: { productId },\n headers: { 'X-CSRFToken': csrftoken },\n success(data) { $('#total-items').text(data.total_items); }\n });\n });\n});\n```\n\n2) Global inline variable (if you prefer to keep data-* minimal):\nTemplate:\n```html\n\n\n```\n\n3) Use cookie + $.ajaxSetup so you don't set headers every request (recommended if you have many AJAX calls). See code in the CSRF section and the gist: https://gist.github.com/sirodoht/fb7a6e98d33fc460d4f1eadaff486e7b.\n\n4) If you're using fetch:\n```javascript\nfetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken },\n body: JSON.stringify({ productId })\n}).then(r => r.json()).then(data => { /* update UI */ });\n```\n\n5) If the external file still doesn't execute, test with a tiny console.log at top of the file to confirm it runs:\n```javascript\nconsole.log('cart.js loaded');\n```\nIf you don't see that message, the file isn't being fetched or executed.\n\n---\n\n## Sources {#sources}\n\n- [Django ajax request from external javascript file - Stack Overflow](https://stackoverflow.com/questions/22688032/django-ajax-request-from-external-javascript-file) \n- [How to pass csrf_token to javascript file in django? - Stack Overflow](https://stackoverflow.com/questions/23349883/how-to-pass-csrf-token-to-javascript-file-in-django) \n- [AJAX post in external JS file with Django - Stack Overflow](https://stackoverflow.com/questions/37160661/ajax-post-in-external-js-file-with-django) \n- [How to Work With AJAX Request With Django — Simple is Better Than Complex](https://simpleisbetterthancomplex.com/tutorial/2016/08/29/how-to-work-with-ajax-request-with-django.html) \n- [Get CSRF token from Django HTML templates with vanilla JS · GitHub Gist](https://gist.github.com/sirodoht/fb7a6e98d33fc460d4f1eadaff486e7b) \n- [How to use Django's CSRF protection](https://docs.djangoproject.com/en/5.2/howto/csrf/) \n- [How to manage static files (e.g. images, JavaScript, CSS) | Django documentation](https://docs.djangoproject.com/en/4.1/howto/static-files/) \n\n---\n\n## Conclusion {#conclusion}\n\nThe most likely cause is that the external file is static (not templated) so your `{% url %}` or other template code isn't being expanded — or the script is loaded in the wrong order / not loaded at all, or the CSRF header isn't being set. For reliable Django AJAX: expose templated values via data-attributes or a tiny inline window variable, ensure static files are served and jQuery loads first, and set X-CSRFToken from a meta tag or cookie (or use $.ajaxSetup). Once you verify the script is fetched, check the console and network tab and you'll find the specific failure quickly."},{"@type":"QAPage","@context":"https://schema.org","mainEntity":{"name":"Why does my Django AJAX work inline but not from external JS?","text":"AJAX works when inline in a Django template but the AJAX request doesn't run when moved to an external .js file. What causes this and how can I fix it?","@type":"Question","acceptedAnswer":{"text":"Most likely cause: external .js files are served as static assets and are NOT processed by Django's template engine, so template tags and variables (for example {% url 'cart:add_to_cart' %} or {{ csrf_token }}) are not expanded. Other common causes: jQuery is loaded after your script ($ is not defined), the external file isn't being served or is cached/stale, the script runs before DOM elements exist (querySelector returns null), or the CSRF header/token is missing resulting in 403. How to fix: expose rendered values via data-* attributes or set a tiny inline window variable in the template and read it from external JS; add a meta tag (e.g., ) or read the csrftoken cookie and set X-CSRFToken on AJAX requests (or use $.ajaxSetup with a getCookie helper); ensure jQuery is loaded before your file and include scripts at the end of the body or use defer; verify the external file loads in DevTools Network and add console.log('cart.js loaded') to confirm execution; use event delegation (e.g., $(document).on('click', '.add-to-cart', handler)) so handlers attach reliably. Following these steps will resolve the majority of external-JS AJAX failures.","@type":"Answer","upvoteCount":1,"dateCreated":"2026-01-05T15:35:48.052Z","datePublished":"2026-01-05T15:35:48.052Z","dateModified":"2026-01-05T15:35:48.052Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"url":"https://neuroanswers.net/c/web/q/fix-django-ajax-external-js/#message-8e9304b0-484d-4c93-970c-8e72fdfecdc1"},"@id":"https://neuroanswers.net/c/web/q/fix-django-ajax-external-js","answerCount":1,"dateCreated":"2026-01-05T15:35:48.052Z","datePublished":"2026-01-05T15:35:48.052Z","dateModified":"2026-01-05T15:35:48.052Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}]},"mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/fix-django-ajax-external-js"},"inLanguage":"en","dateCreated":"2026-01-05T15:35:48.052Z","datePublished":"2026-01-05T15:35:48.052Z","dateModified":"2026-01-05T15:35:48.052Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"@id":"https://neuroanswers.net/c/web/q/fix-django-ajax-external-js"},{"@type":"CollectionPage","@id":"https://neuroanswers.net/c/web/q/fix-django-ajax-external-js/#related-questions","name":"Fix Django AJAX in External JS Files: Causes & Fixes","description":"Troubleshoot Django AJAX failing in external JavaScript: learn why template tags, static file loading order, and CSRF tokens break requests and how to fix them.","url":"https://neuroanswers.net/c/web/q/fix-django-ajax-external-js","inLanguage":"en","mainEntity":{"@type":"ItemList","@id":"https://neuroanswers.net/c/web/q/fix-django-ajax-external-js/#related-questions","itemListElement":[{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/jquery-ajax-file-upload-formdata-php","name":"jQuery AJAX File Upload with FormData to PHP Guide","position":1,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/jquery-ajax-file-upload-formdata-php","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/jquery-ajax-file-upload-formdata-php"},"inLanguage":"en","dateCreated":"2026-02-22T16:38:16.799Z","datePublished":"2026-02-22T16:38:16.799Z","dateModified":"2026-02-23T13:35:25.194Z","author":[{"@type":"Person","@id":"https://neuroanswers.net/@raphael-schweikert","name":"Raphael Schweikert","givenName":"Raphael","familyName":"Schweikert","url":"https://neuroanswers.net/@raphael-schweikert","jobTitle":"Software Developer","description":"Software developer focused on completing projects correctly and efficiently, with a strong interest in learning new programming languages."},{"@type":"Person","@id":"https://neuroanswers.net/@zoku","name":"@zoku","url":"https://neuroanswers.net/@zoku","jobTitle":"Software Developer","description":"Professional software developer from Germany specializing in Kotlin, JavaScript, HTML/CSS, and PHP including WordPress."},{"@type":"Person","@id":"https://neuroanswers.net/@webinista","name":"@webinista","url":"https://neuroanswers.net/@webinista","jobTitle":"Freelance Web Developer","description":"Front-end specialist and LAMP stack developer based in Los Angeles, experienced with WordPress themes, Liquid for Shopify/NationBuilder, Python, and former Opera Developer Relations team member."},{"@type":"Person","@id":"https://neuroanswers.net/@mdn-contributors","name":"@mdn-contributors","url":"https://neuroanswers.net/@mdn-contributors","jobTitle":"Community Contributor","description":"MDN contributors are a community of developers who write and maintain documentation for web standards"},{"@type":"Person","@id":"https://neuroanswers.net/@codexworld","name":"@codexworld","url":"https://neuroanswers.net/@codexworld","image":{"@type":"ImageObject","url":"https://neuroanswers.net/api/v1/person/codexworld/avatar.png","width":"72","height":"72"},"jobTitle":"Technical Writer","description":"Author and representative for CodexWorld's programming blog, providing tutorials on web development, PHP, MySQL, and related technologies."},{"@type":"Person","@id":"https://neuroanswers.net/@d-cochran","name":"@d-cochran","url":"https://neuroanswers.net/@d-cochran","jobTitle":"Web Developer","description":"Independent web developer and blogger covering PHP, JavaScript/jQuery, MySQL, file handling, CSV processing, and HTML5 game frameworks."}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"jQuery AJAX File Upload with FormData to PHP Guide","description":"Learn how to upload files using jQuery.ajax() and FormData with multipart/form-data to PHP. Fix empty $_POST issues, add progress bars, and ensure Safari 5+ compatibility for seamless file uploads.","keywords":["jquery ajax","file upload","formdata","multipart form-data","php file upload","ajax file upload","jquery file upload","formdata ajax","php upload file"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/setting-checkbox-states-jquery-modal-windows","name":"Setting Checkbox States in jQuery Modal Windows","position":2,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/setting-checkbox-states-jquery-modal-windows","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/setting-checkbox-states-jquery-modal-windows"},"inLanguage":"en","dateCreated":"2026-02-02T12:43:02.399Z","datePublished":"2026-02-02T12:43:02.399Z","dateModified":"2026-02-02T12:43:02.399Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"Setting Checkbox States in jQuery Modal Windows","description":"Learn how to properly set checkbox states in jQuery modal windows using .prop() method and proper event timing for reliable form behavior.","keywords":["jquery checkbox","jquery modal","jquery checkbox checked","jquery modal window","jquery prop checked","jquery set checkbox","jquery checkbox modal","jquery modal checkbox","modal checkbox state","jquery form handling","jquery dom manipulation"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/jquery-html-escaping-xss-prevention","name":"jQuery HTML Escaping: Prevent XSS with Safe Methods","position":3,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/jquery-html-escaping-xss-prevention","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/jquery-html-escaping-xss-prevention"},"inLanguage":"en","dateCreated":"2026-01-28T11:13:14.927Z","datePublished":"2026-01-28T11:13:14.927Z","dateModified":"2026-01-28T11:13:14.927Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"jQuery HTML Escaping: Prevent XSS with Safe Methods","description":"Learn how to escape HTML strings in jQuery to prevent XSS attacks. Discover safe methods like .text(), .parseHTML(), and programmatic DOM creation for secure content display.","keywords":["jquery html","html encode","javascript xss","jquery text","jquery parsehtml","xss prevention","dom creation","web security","jquery security"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/pass-data-id-to-bootstrap-modal-from-link","name":"Pass Data ID to Bootstrap Modal from Hyperlink","position":4,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/pass-data-id-to-bootstrap-modal-from-link","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/pass-data-id-to-bootstrap-modal-from-link"},"inLanguage":"en","dateCreated":"2026-02-17T16:29:52.808Z","datePublished":"2026-02-17T16:29:52.808Z","dateModified":"2026-02-17T16:29:52.808Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/@stackoverflow-com","name":"Stack Overflow","description":"Q&A for professional and enthusiast programmers. It's built and run by the community as part of the Stack Exchange network of Q&A sites. With community contributions, they work together to build a library of detailed, high-quality answers to every question about programming.","url":"https://neuroanswers.net/@stackoverflow-com","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/api/v1/source/stackoverflow-com/logo.png","width":"72","height":"72"}},{"@type":"Organization","@id":"https://neuroanswers.net/@getbootstrap-com","name":"Bootstrap","description":"Free and open-source CSS framework for responsive mobile-first websites","url":"https://neuroanswers.net/@getbootstrap-com","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/api/v1/source/getbootstrap-com/icon.png","width":"72","height":"72"}},{"@type":"Organization","@id":"https://neuroanswers.net/@sqlpey-com","name":"sqlpey","description":"Technical blog on JavaScript, CSS, web development, and frameworks.","url":"https://neuroanswers.net/@sqlpey-com","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/api/v1/source/sqlpey-com/logo.png","width":"72","height":"72"}},{"@type":"Person","@id":"https://neuroanswers.net/@mg1075","name":"@mg1075","url":"https://neuroanswers.net/@mg1075","jobTitle":"Answer author","description":"Stack Overflow contributor"},{"@type":"Person","@id":"https://neuroanswers.net/@lostincomputer","name":"@lostincomputer","url":"https://neuroanswers.net/@lostincomputer","jobTitle":"Answer author","description":"Stack Overflow contributor"},{"@type":"Person","@id":"https://neuroanswers.net/@rmbits","name":"@rmbits","url":"https://neuroanswers.net/@rmbits","jobTitle":"Answer author","description":"Stack Overflow user with 2,347 reputation"},{"@type":"Person","@id":"https://neuroanswers.net/@leon-cullens","name":"Leon Cullens","givenName":"Leon","familyName":"Cullens","url":"https://neuroanswers.net/@leon-cullens","jobTitle":"Question author","description":"Stack Overflow user with 12,536 reputation, active in C#, .NET, Entity Framework"}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"Pass Data ID to Bootstrap Modal from Hyperlink","description":"Learn how to pass a unique data-id from a link to a hidden input in Bootstrap modal using show.bs.modal event and relatedTarget. Fix common issues with data-toggle, BS4/BS5 examples, and troubleshooting for reliable dynamic modals.","keywords":["bootstrap modal","pass data to modal","data toggle modal","show.bs.modal","bootstrap 5 modal","modal data attributes","relatedtarget","bootstrap modal open","bootstrap modal js"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/vanilla-javascript-domcontentloaded-document-ready-equivalent","name":"Vanilla JavaScript DOMContentLoaded: Document Ready Equivalent","position":5,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/vanilla-javascript-domcontentloaded-document-ready-equivalent","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/vanilla-javascript-domcontentloaded-document-ready-equivalent"},"inLanguage":"en","dateCreated":"2026-02-05T11:09:45.984Z","datePublished":"2026-02-05T11:09:45.984Z","dateModified":"2026-02-05T11:09:45.984Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"Vanilla JavaScript DOMContentLoaded: Document Ready Equivalent","description":"Learn the vanilla JavaScript equivalent of jQuery's $(document).ready() using DOMContentLoaded event. Execute code after DOM is fully loaded without jQuery.","keywords":["addeventlistener","document ready","DOMContentLoaded","javascript dom","document addeventlistener domcontentloaded","js document ready","jquery document ready","vanilla javascript","domcontentloaded event","javascript dom ready","dom ready javascript","jquery equivalent","dom manipulation","javascript events","dom loaded"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/debug-django-500-menu-decimal-nan","name":"Debug Django 500 Error on /menu/ - Decimal & Template Fixes","position":6,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/debug-django-500-menu-decimal-nan","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/debug-django-500-menu-decimal-nan"},"inLanguage":"en","dateCreated":"2026-01-14T11:04:10.098Z","datePublished":"2026-01-14T11:04:10.098Z","dateModified":"2026-01-14T11:04:10.098Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"Debug Django 500 Error on /menu/ - Decimal & Template Fixes","description":"Fix intermittent Django 500s on /menu/ by debugging template rendering and DecimalField NaNs. Steps: locate NaNs, sanitize DB, add template guards and logging.","keywords":["django template","django 500 error","template rendering","decimalfield","nan values","production debugging","django debugging","numberformat"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/django-react-ios-compatibility-guide","name":"Django+React iOS Compatibility Guide: Fix Loading Issues on Older Devices","position":7,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/django-react-ios-compatibility-guide","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/django-react-ios-compatibility-guide"},"inLanguage":"en","dateCreated":"2026-04-06T13:52:32.864Z","datePublished":"2026-04-06T13:52:32.864Z","dateModified":"2026-04-06T13:52:32.864Z","author":[{"@type":"Person","@id":"https://neuroanswers.net/@apple-developer-team","name":"Apple Developer","givenName":"Apple","familyName":"Developer","url":"https://neuroanswers.net/@apple-developer-team","jobTitle":"Documentation Writer","description":"Official Apple developer documentation team"},{"@type":"Organization","@id":"https://neuroanswers.net/@developer-apple-com","name":"Apple Developer","description":"Official Apple developer documentation for Safari and related technologies","url":"https://neuroanswers.net/@developer-apple-com"},{"@type":"Person","@id":"https://neuroanswers.net/@apple-support-team","name":"Apple Support","givenName":"Apple","familyName":"Support","url":"https://neuroanswers.net/@apple-support-team","jobTitle":"Support Specialist","description":"Official Apple support documentation team"},{"@type":"Organization","@id":"https://neuroanswers.net/@support-apple-com","name":"Apple Support","description":"Official Apple support documentation for iPhone","url":"https://neuroanswers.net/@support-apple-com"},{"@type":"Person","@id":"https://neuroanswers.net/@can-i-use-team","name":"Can I Use","givenName":"Can","familyName":"I Use","url":"https://neuroanswers.net/@can-i-use-team","jobTitle":"Web Compatibility Expert","description":"Team behind the Can I Use browser compatibility database"},{"@type":"Organization","@id":"https://neuroanswers.net/@caniuse-com","name":"Can I Use","description":"Browser support tables for web technologies on iOS","url":"https://neuroanswers.net/@caniuse-com","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/api/v1/source/caniuse-com/icon.png","width":"72","height":"72"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"Django+React iOS Compatibility Guide: Fix Loading Issues on Older Devices","description":"Troubleshoot Django+React website loading failures on older iOS devices. Learn about network protocol issues, server configuration, and optimization steps for iOS compatibility.","keywords":["ios compatibility","django react mobile compatibility","mobile web issues","web development compatibility","ios below version 26","vpn solves ios issues","django react ios 26 compatibility","mobile web django react compatibility","ios version specific web issues","django react mobile safari issues"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/php-popup-form-row-data-fix-first-row-issue","name":"PHP Popup Form Row Data: Fix First Row Issue","position":8,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/php-popup-form-row-data-fix-first-row-issue","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/php-popup-form-row-data-fix-first-row-issue"},"inLanguage":"en","dateCreated":"2025-12-22T16:06:38.328Z","datePublished":"2025-12-22T16:06:38.328Z","dateModified":"2025-12-22T16:06:38.328Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"PHP Popup Form Row Data: Fix First Row Issue","description":"Fix PHP popup form always getting first row data. Learn how to pass correct row reference numbers to popup forms using JavaScript, hidden inputs, and proper form handling.","keywords":["php form","php data","php table","php javascript","ajax php","popup form","row data","reference number","hidden input","form submission"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/django-many-to-many-through-fields-order-fix","name":"Fix Django self-referential ManyToMany through_fields","position":9,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/django-many-to-many-through-fields-order-fix","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/django-many-to-many-through-fields-order-fix"},"inLanguage":"en","dateCreated":"2025-12-28T10:04:28.880Z","datePublished":"2025-12-28T10:04:28.880Z","dateModified":"2025-12-28T10:04:28.880Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"Fix Django self-referential ManyToMany through_fields","description":"Swap through_fields order to fix reversed user_from/user_to in Django self-referential ManyToMany through model. Examples, migration steps, and data-fix tips.","keywords":["django many to many","through_fields","through model","self-referential manytomany","user_from user_to","django ORM","followers following","data migration","unique constraint"],"image":[],"articleBody":""}},{"@type":"ListItem","@id":"https://neuroanswers.net/c/web/q/fix-npm-error-could-not-determine-executable-tailwindcss-django","name":"Fix 'npm error could not determine executable' Tailwind Django","position":10,"item":{"@type":"Article","@id":"https://neuroanswers.net/c/web/q/fix-npm-error-could-not-determine-executable-tailwindcss-django","mainEntityOfPage":{"@type":"WebPage","@id":"https://neuroanswers.net/c/web/q/fix-npm-error-could-not-determine-executable-tailwindcss-django"},"inLanguage":"en","dateCreated":"2026-01-02T16:06:59.205Z","datePublished":"2026-01-02T16:06:59.205Z","dateModified":"2026-01-02T16:06:59.205Z","author":[{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}}],"publisher":{"@type":"Organization","@id":"https://neuroanswers.net/about","name":"NeuroAnswers","url":"https://neuroanswers.net/about","logo":{"@type":"ImageObject","url":"https://neuroanswers.net/logo.png","width":"512","height":"512"}},"headline":"Fix 'npm error could not determine executable' Tailwind Django","description":"Resolve 'npm error could not determine executable to run' when running npx tailwindcss init in Django on Windows PowerShell. Step-by-step Tailwind CSS v4 setup with Vite plugin for Django projects.","keywords":["npx tailwindcss init","npm error could not determine executable to run","tailwind css v4","django tailwind","vite tailwind css","tailwindcss init error","npm error enoent","tailwind css install","tailwind css config"],"image":[],"articleBody":""}}]}}]}
Web

Fix Django AJAX in External JS Files: Causes & Fixes

Troubleshoot Django AJAX failing in external JavaScript: learn why template tags, static file loading order, and CSRF tokens break requests and how to fix them.

1 answer 1 view

Why does my Django AJAX code work when the JavaScript is inline in the template but not when it’s moved to an external .js file? I can successfully read the product ID and CSRF token from data attributes and jQuery is loaded, but the AJAX request doesn’t run when the code is in an external file. Example HTML and JavaScript:

HTML:

html
<main data-item-id="{{ product.id }}" data-csrf-token="{{ csrf_token }}">

JavaScript:

javascript
$(document).ready(function(){
var btn = document.querySelector(".add-to-cart");
var productId = document.querySelector('main').getAttribute('data-item-id');
var csrfToken = document.querySelector('main').getAttribute('data-csrf-token');
btn.addEventListener("click", function(){
 $.ajax({
 type: 'POST',
 url: '{% url "cart:add_to_cart"%}',
 data: {'productId': productId},
 headers: {'X-CSRFToken': csrfToken},
 success: function(data){
 $("#total-items").text(data.total_items);
 }
 })
})
})

I also have the script tag and jQuery included. What could be causing the external JS file not to execute the AJAX request, and how can I fix it (considering Django template tags, CSRF, and serving static JS)?

Your AJAX works when the JavaScript is inline because Django processes template tags and template variables in the HTML; external .js files are served as static assets and aren’t run through the Django template engine, so things like {% url "cart:add_to_cart" %} won’t be expanded. Other frequent causes are wrong script load order (jQuery loaded after your file), the static file not actually being served, or a missing/incorrect CSRF header — fix these by exposing templated values in the DOM (data-attributes or a tiny inline var), ensuring the correct static include order, and reading/setting the CSRF token from a meta tag or cookie before sending AJAX requests.


Contents


Django AJAX and Template Tags

Why does inline work? Simple: when your JavaScript lives inside a Django template the template engine replaces template tags and variables (for example {% url ... %} and {{ csrf_token }}) with real strings before the browser sees the page. An external static file is not processed by Django’s template engine, so any template tag inside it remains raw text and will not provide the correct URL or token.

Symptoms of this exact problem:

  • In the browser network tab the AJAX request goes to an odd URL like /%7B%25%20url%20%22cart:add_to_cart%22%20%25%7D or you see no outbound request at all.
  • There are no AJAX responses or the server returns 404/400 because the endpoint is wrong.

Two practical patterns to avoid putting template tags in external .js:

  1. Put the URL (and any other templated values) on the DOM as data attributes and read them from your external script:

Template:

html
<button class="add-to-cart"
 data-url="{% url 'cart:add_to_cart' %}"
 data-item-id="{{ product.id }}"
 data-csrf-token="{{ csrf_token }}">
 Add
</button>

External JS:

javascript
const btn = document.querySelector('.add-to-cart');
const url = btn.dataset.url; // reads the rendered URL
const productId = btn.dataset.itemId;
const csrfToken = btn.dataset.csrfToken;
// then call $.ajax({ url, ... })
  1. Or set a tiny inline variable before loading the external file:

Template:

html
<script>window.ADD_TO_CART_URL = "{% url 'cart:add_to_cart' %}";</script>
<script src="{% static 'js/cart.js' %}"></script>

External JS:

javascript
const url = window.ADD_TO_CART_URL;

Both approaches remove template tags from static files and keep your JS static and cacheable. See common community discussion about passing the CSRF token or URLs from templates to JS: https://stackoverflow.com/questions/23349883/how-to-pass-csrf-token-to-javascript-file-in-django and https://stackoverflow.com/questions/22688032/django-ajax-request-from-external-javascript-file.


Django Static Files: correct loading & order

If your external file never runs the most common causes are: wrong static path, the browser not loading the file, or wrong script order (jQuery loaded after your code). Quick checks and fixes:

  • Use Django’s static tag and make sure django.contrib.staticfiles is in INSTALLED_APPS:
django
{% load static %}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="{% static 'js/cart.js' %}"></script>
  • Put static script includes at the end of the body or use defer so the DOM is ready when the script runs.
  • In development, confirm the script file returns 200 in DevTools Network. In production, run collectstatic and configure your webserver to serve static files; see Django docs on static files: https://docs.djangoproject.com/en/4.1/howto/static-files/.
  • Clear browser cache or use hashed filenames (ManifestStaticFilesStorage) to avoid stale cached JS.

If jQuery is not defined when your external code runs you’ll see console errors like Uncaught ReferenceError: $ is not defined. Fix the include order (jQuery first) or use an AMD/bundler/defer approach.


Django CSRF in external JavaScript

You already read the CSRF token from a data attribute — that’s valid. But common pitfalls:

  • Putting {% csrf_token %} inside a script tag incorrectly can produce a JS syntax error (don’t output raw token text without quoting).
  • If you try to read the CSRF token from cookie but you enabled CSRF_COOKIE_HTTPONLY = True, JavaScript won’t be able to read it.
  • External JS must set the X-CSRFToken header (or include the token in POST data) for non-safe requests.

Recommended safe patterns

  1. Meta tag or data attribute + header per-request:
    Template:
html
<meta name="csrf-token" content="{{ csrf_token }}">

External JS:

javascript
const csrftoken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

$.ajax({
 type: 'POST',
 url: url,
 data: { productId },
 headers: { 'X-CSRFToken': csrftoken }
});
  1. Read from cookie (vanilla getCookie) and set up $.ajax globally. Example getCookie from a community gist: https://gist.github.com/sirodoht/fb7a6e98d33fc460d4f1eadaff486e7b
javascript
function getCookie(name) {
 let cookieValue = null;
 if (document.cookie && document.cookie !== '') {
 const cookies = document.cookie.split(';');
 for (let i = 0; i < cookies.length; i++) {
 const cookie = cookies[i].trim();
 if (cookie.substring(0, name.length + 1) === (name + '=')) {
 cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
 break;
 }
 }
 }
 return cookieValue;
}
const csrftoken = getCookie('csrftoken');

$.ajaxSetup({
 beforeSend: function(xhr, settings) {
 if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
 xhr.setRequestHeader("X-CSRFToken", csrftoken);
 }
 }
});

Django documents this header technique here: https://docs.djangoproject.com/en/5.2/howto/csrf/.


Common runtime errors and debugging checklist

When your inline version works but external doesn’t, follow this checklist — they solve 90% of cases:

  • Open DevTools → Console: any errors? Uncaught ReferenceError: $ is not defined, TypeError: Cannot read property 'addEventListener' of null, or a SyntaxError will stop execution.
  • Network tab: is the external .js fetched (200)? Is the AJAX request being sent at all? If yes, what is the request URL and status code (403 = CSRF failed, 404 = wrong URL)?
  • Confirm script order: jQuery first, then your script. If you see $ is not defined fix order.
  • Confirm your template tags are not inside the external .js. If you see literal {% url ... %} in the JS or in the request URL, move the tag into the HTML (data- attribute or inline window. var).
  • Check that your selector finds the element: document.querySelector('.add-to-cart') can be null if the element isn’t present. Use event delegation as needed: $(document).on('click', '.add-to-cart', handler).
  • Check CSRF: if server returns 403, inspect request headers to see if X-CSRFToken was sent; ensure you’re reading the correct token source (cookie vs meta vs data attribute).
  • Spelling options: jQuery uses dataType (capital T). A wrong option name can be ignored; it won’t usually break the request but is worth checking.
  • If you use HTMX or replace DOM segments dynamically, scripts may need re-initialization — prefer event delegation.

If you’re unsure, paste the external JS URL into the browser to inspect the delivered file. That quickly shows whether a template tag remains unrendered or whether the file is stale/cached.


Quick fixes and recommended code samples

  1. Minimal and robust — data-attribute + jQuery post:
    Template:
html
<button class="add-to-cart"
 data-url="{% url 'cart:add_to_cart' %}"
 data-item-id="{{ product.id }}"
 data-csrf="{{ csrf_token }}">
 Add
</button>

External JS:

javascript
$(function(){
 $(document).on('click', '.add-to-cart', function(){
 const btn = this;
 const url = btn.dataset.url;
 const productId = btn.dataset.itemId;
 const csrftoken = btn.dataset.csrf; // or from meta/cookie
 $.ajax({
 type: 'POST',
 url: url,
 data: { productId },
 headers: { 'X-CSRFToken': csrftoken },
 success(data) { $('#total-items').text(data.total_items); }
 });
 });
});
  1. Global inline variable (if you prefer to keep data-* minimal):
    Template:
html
<script>window.ADD_TO_CART_URL = "{% url 'cart:add_to_cart' %}";</script>
<script src="{% static 'js/cart.js' %}"></script>
  1. Use cookie + $.ajaxSetup so you don’t set headers every request (recommended if you have many AJAX calls). See code in the CSRF section and the gist: https://gist.github.com/sirodoht/fb7a6e98d33fc460d4f1eadaff486e7b.

  2. If you’re using fetch:

javascript
fetch(url, {
 method: 'POST',
 headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken },
 body: JSON.stringify({ productId })
}).then(r => r.json()).then(data => { /* update UI */ });
  1. If the external file still doesn’t execute, test with a tiny console.log at top of the file to confirm it runs:
javascript
console.log('cart.js loaded');

If you don’t see that message, the file isn’t being fetched or executed.


Sources


Conclusion

The most likely cause is that the external file is static (not templated) so your {% url %} or other template code isn’t being expanded — or the script is loaded in the wrong order / not loaded at all, or the CSRF header isn’t being set. For reliable Django AJAX: expose templated values via data-attributes or a tiny inline window variable, ensure static files are served and jQuery loads first, and set X-CSRFToken from a meta tag or cookie (or use $.ajaxSetup). Once you verify the script is fetched, check the console and network tab and you’ll find the specific failure quickly.

Authors
Verified by moderation
NeuroAnswers
Moderation
Fix Django AJAX in External JS Files: Causes & Fixes