Simple Django w/ Svelte
Tags: svelte, django, webdev
Published: 2021-03-24 00:25:41

# Forewarning
If you are serious about using Django and Svelte you probably just want [djangorestframework pkg](https://pypi.org/project/djangorestframework/) and [django-svelte pkg](https://pypi.org/project/django-svelte/). This will get you two major things:
* pass prop data to svelte components
* POST/PUT/UPDATE/DELETE data via API calls from svelte components. Aka modify and submit data, turning this into a useful two way street as you won't be able to use Django's nice builtin forms.

Final Example: https://gitlab.com/mdpb/svelte-django-example

# Goal
I figured [rollup](https://rollupjs.org/guide/en/) turned svelte into a basic .html and .js file, so why not just host those from specific routes in Django? 

This way you could rely on the templating in Django, stay in Python land as long as possible, then push a Svelte component or mini-Singe Page Application to the user.

### Why?
Some of you may think this setup sounds like old news, or hail from the olden times of Apache servers and the /www directory.  But for me the easiest and most familiar path is working 100% on a Single Page App with react/svelte/vue and then pushing it to a CDN via some service like [Vercel](https://vercel.com/guides/deploying-svelte-with-vercel).

After the frontend code, written in 100% modern javascript, then you make `fetch` requests to populate the site with data.  So you end up making CORS requests.  That works fine, little learning curve with CORS if you own the resource you're fetching from.

But it lacks a certain simplicity.  I wanted to live on one single domain and manage everything from a single language + framework as much as possible.

### Getting into it
1. Build your svelte component(s) locally.
1. Compile your svelte page(s) and send them to the `static` directory for your Django app.
1. Return a Template from your Route's View like normal, except the .html file you return is gonna have a few extra `<script>` and `<link>` tags:
```
<head>
    <script 
        type="module" 
        src="{% static 'notes/bundle.js' %}">
    </script>
    <link 
        rel='stylesheet' 
        href="{% static 'notes/bundle.css' %}">
    <link 
        rel='stylesheet' 
        href="{% static 'css/global.css' %}">
</head>

```

This won't leave you with much, you'll be able to send a svelte file off to the user but 
* you won't be able to push Django data into it
* you won't be able to submit data as simply as standard Django form

But hey! You're pushing svelte out client side!

### Details
Start with your URL route:
```python
#your_app/urls.py
...
urlpatterns = [
    path('new/svelte/', views.svelte, name='new'),
]
...
```

You'll need a View for that:
```python
#your_app/views.py
def svelte(request):
    template = loader.get_template('notes/new-svelte.html')
    return HttpResponse(template.render(context=None, request=request))
```

And of course a Template:
```
<!-- your_app/template/your_app/new-svelte.html -->
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <script type="module" src="{% static 'notes/bundle.js' %}"></script>
    <link rel='stylesheet' href="{% static 'notes/bundle.css' %}">
    <link rel='stylesheet' href="{% static 'css/global.css' %}">
</head>

<body>
    <noscript>ah shucks. you should see a svelte component, 
not this message :/ enable javascript if you wanna use svelte</noscript>
</body>
</html>
```

If you copy pasted the above code you should be seeing your svelte app when you go to `localhost/your_app/new/svelte`.

### Serving Static Files in Django
You may need to add `'django.contrib.staticfiles'` to your settings.py INSTALLED_APPS[] but this is worth reading: https://docs.djangoproject.com/en/3.1/howto/static-files/


# Sources:
This article was instrumental: https://dev.to/ashraf_zolkopli/django-svelte-best-dev-experience-dx-1848

But the raw source is here: https://gitlab.com/mdpb/svelte-django-example