Skip to content

Instantly share code, notes, and snippets.

@danjac
danjac / download_csv.py
Created June 14, 2024 12:15
Django CSV download using StreamingHttpResponse
import csv
class CSVBuffer:
"""Handles CSV output."""
def write(self, value):
"""Handles file-like write, just returning the value"""
return value
def download_csv(request):
@danjac
danjac / form.html
Last active March 12, 2024 15:52
Django form using AlpineJS to render rating field
{#
class ReviewForm(forms.ModelForm):
class Meta:
model = Review
fields = (
"comment",
"score",
)
help_texts: ClassVar = {
@danjac
danjac / markdown_test.py
Created December 31, 2023 09:25
Using pytest.param with parametrize
class TestMarkdown:
@pytest.mark.parametrize(
("value", "expected"),
[
pytest.param(None, "", id="none"),
pytest.param("", "", id="empty"),
pytest.param("test", "<p>test</p>\n", id="text"),
pytest.param(" ", "", id="space"),
pytest.param("<p>test</p>", "<p>test</p>", id="html"),
pytest.param("<p>test</p> ", "<p>test</p>", id="html and spaces"),
@danjac
danjac / cover-image.js
Last active November 29, 2023 18:39
HTML component for rendering image with fallback to placeholder
class CoverImage extends HTMLElement {
/*
Usage:
<cover-image placeholder="placeholder.jpg">
<img src="cover.jpg" loading"lazy">
</cover-image>
*/
connectedCallback() {
const images = this.querySelectorAll("img");
const placeholder = this.getAttribute("placeholder");
@danjac
danjac / htmx_fragments.py
Created June 30, 2023 09:33
Django helper function to render one or more template blocks with HTMX
from django.http import HttpRequest, HttpResponse
from django.template.response import TemplateResponse
from render_block import render_block_to_string
def render_template_fragments(
request: HttpRequest,
template_name: str,
context: dict | None = None,
*,
@danjac
danjac / form_views.py
Created June 26, 2023 07:34
Form handler function
# https://docs.djangoproject.com/en/4.2/topics/forms/
# original example
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == "POST":
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
@danjac
danjac / form_views.py
Created June 26, 2023 07:25
Tidier form validation
# example from Django docs https://docs.djangoproject.com/en/4.2/topics/forms/
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == "POST":
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
@danjac
danjac / method_dispatcher.py
Created June 25, 2023 10:37
Decorator to dispatch to different functions based on HTTP methods
def method_dispatcher(view: Callable) -> Callable:
"""Dispatch for method. Turns view into decorator so you can do:
@method_dispatcher
def my_view(request):
return HttpResponse()
@method_dispatcher("POST", "PUT")
def submit(request):
<?xml version='1.0' encoding='UTF-8'?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:podcast="https://podcastindex.org/namespace/1.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel><atom:link href="https://feeds.buzzsprout.com/1889177.rss" rel="self" type="application/rss+xml" /><atom:link href="https://pubsubhubbub.appspot.com/" rel="hub" xmlns="http://www.w3.org/2005/Atom" /><title>4 Legal English Podcast</title><lastBuildDate>Sat, 11 Feb 2023 07:35:34 -0500</lastBuildDate><link>http://www.4legalenglish.com</link><language>en-us</language><copyright>© 2023 4 Legal English Podcast</copyright><podcast:locked>yes</podcast:locked><podcast:guid>081a03d5-b634-521a-b546-ed83ff470077</podcast:guid><itunes:author>Timothy Barrett</itunes:author><itunes:type>episodic</itunes:type><itunes:explicit>false</itunes:explicit><description><![CDATA[4 Legal English Podcast is for lawyers, law students, and other professionals fro
@danjac
danjac / tailwind.config.js
Last active March 30, 2021 08:10
Typography+dark mode
module.exports = {
darkMode: 'class',
future: {
removeDeprecatedGapUtilities: true,
purgeLayersByDefault: true,
},
purge: {
content: ['./templates/**/*.html', './static/src/js/**/*.js', './safelist.txt'],
keyframes: true,
},