matthiask / blacknoise

MIT License
33 stars 0 forks source link

Looking for Django example #1

Open pySilver opened 3 weeks ago

pySilver commented 3 weeks ago

Hi!

Thanks for interesting package! Do you mind to create some basic Django integration example with ManifestStaticFilesStorage support? I believe this is what most people do in production.

matthiask commented 3 weeks ago

Hi @pySilver

Thanks for the nice words :)

Good idea, I should maybe expand upon that a bit. But really, it should just work with the example I provided in the README. If you have STATIC_URL = "/static/", an appropriate STATIC_ROOT value, and of course the ManifestStaticFilesStorage configured, the asgi.py file in the README can be used as-is.

Here's a real life example:

https://github.com/matthiask/traduire/blob/main/asgi.py https://github.com/matthiask/traduire/blob/5e58e726874e2e480fc13cadba8cc3d931da6c6d/app/settings.py#L52-L71

Blacknoise currently doesn't have deeper integration with Django like the Whitenoise middleware and whatnot.

I'm interested to hear more if you hit any issues with the package.

pySilver commented 3 weeks ago

Wow! Thanks for quick reply. This approach looks really tiny and straightforward. I'll definitely try it out.

pySilver commented 3 weeks ago

@matthiask I assume this approach works great in production but on local development it requires:

So basically local development may use something like that:

if settings.DEBUG:
    django_application = get_asgi_application()
else:
    django_application = BlackNoise(
        get_asgi_application(),
        immutable_file_test=lambda *a: True,
    )
    django_application.add(BASE_DIR / "staticfiles", "/static/")
matthiask commented 3 weeks ago

Good point. I'm using staticfiles_urlpatterns in development when using an ASGI server, see https://docs.djangoproject.com/en/5.1/ref/contrib/staticfiles/#django.contrib.staticfiles.urls.staticfiles_urlpatterns

Sometimes the standard runserver command (which automatically serves static files) is good enough because only a few views are actually asynchronous, but when using "uvicorn --reload" or something you have to use the additional URLconf entry.

pySilver commented 3 weeks ago

Yep, I'm using staticfiles_urlpatterns too:

if settings.DEBUG:
    # Static file serving when using Gunicorn + Uvicorn for local web socket development
    urlpatterns += staticfiles_urlpatterns()

I find Blacknoise solution the easiest among alternatives:

It just need a little bit more marketing / explanation for newcomers (imho)

matthiask commented 3 weeks ago

Thank you! Yes, this thread will help with writing some additional onboarding documentation.

I agree re. marketing, that's always a weak point with my projects :-/

pySilver commented 4 days ago

@matthiask any reason why I'm seeing this:

INFO:     127.0.0.1:62280 - "GET /static/debug_toolbar/css/print.css HTTP/1.1" 304 Not Modified
INFO:     127.0.0.1:62281 - "GET /static/debug_toolbar/js/utils.js HTTP/1.1" 304 Not Modified
2024-09-11T11:56:12.827839Z [info     ] request_started                [django_structlog.middlewares.request] extra={} ip=127.0.0.1 request=GET /static/images/favicons/favicon.ico request_id=e420a6c3-d1c6-4473-9294-fefa0b73a416 user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 user_id=None
2024-09-11T11:56:12.827839Z [info     ] request_started                [django_structlog.middlewares.request] extra={} ip=127.0.0.1 request=GET /static/images/favicons/favicon.ico request_id=e420a6c3-d1c6-4473-9294-fefa0b73a416 user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 user_id=None
2024-09-11T11:56:12.833347Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 extra={} ip=127.0.0.1 request=GET /static/images/favicons/favicon.ico request_id=e420a6c3-d1c6-4473-9294-fefa0b73a416 user_id=None
2024-09-11T11:56:12.833347Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 extra={} ip=127.0.0.1 request=GET /static/images/favicons/favicon.ico request_id=e420a6c3-d1c6-4473-9294-fefa0b73a416 user_id=None
/Users/Silver/Projects/GitHub/mybaze/.venv/lib/python3.12/site-packages/django/http/response.py:517: Warning: StreamingHttpResponse must consume synchronous iterators in order to serve them asynchronously. Use an asynchronous iterator instead.

Similar issue has been fixed in ServeStatic recently: https://github.com/Archmonger/ServeStatic/issues/11

matthiask commented 4 days ago

Hmm no, I haven't seen this yet. The ServeStatic fix seems quite large for something which essentially sounds like a misbehavior in Django. I wonder if it is even a blacknoise issue at all, since we're wrapping the ASGI app, and not descending into Django at all. Isn't the problem maybe that StreamingHttpResponse should use an async file I/O library when running under ASGI?

Also, I'm not sure if it's high priority since it's just a warning.

pySilver commented 3 days ago

Och, you are absolutely right. This observation is not related to BlackNoise at all as I don't use it during development. Silly me.