Django comparison
Route, view, form, ORM and security equivalences.
● ● ●
-- Django (urls.py)
urlpatterns = [
path("articles/", views.article_list, name="article_list"),
path("articles/<id>/", views.article_detail, name="article_detail"),
]
-- Runique (url.rs)
urlpatterns! {
"/articles" => view! { article_list }, name = "article_list",
"/articles/{id}" => view! { article_detail }, name = "article_detail",
}
-- Django (views.py)
def article_list(request):
articles = Article.objects.all()
return render(request, "articles.html", {"articles": articles})
-- Runique (views.rs)
pub async fn article_list(mut request: Request) -> AppResult<Response> {
let db = request.engine.db.clone();
let articles = Article::objects.all().all(&*db).await?;
context_update!(request => { "articles" => &articles });
request.render("articles.html")
}
-- Django (models.py)
class Article(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
-- Runique (entities/article.rs)
model! {
Article,
table: "article",
pk: id => i32,
fields: {
title: text [max_length: 255, required],
content: text [required],
author_id: i32 [required],
},
relations: {
belongs_to: user via author_id [cascade],
}
}
impl_objects!(Article);
-- Django (forms.py)
if form.is_valid():
title = form.cleaned_data["title"]
-- Runique (views.rs)
if form.is_valid().await {
// Simplified direct access
let title = form.cleaned_string("title").unwrap_or_default();
// Or whitelist (POST > URL)
let search = form.cleaned_string("search").unwrap_or_default();
}
-- Django (settings.py)
SECRET_KEY = "..."
DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", ... } }
DEBUG = True
-- Runique (.env + main.rs)
SECRET_KEY=...
DATABASE_URL=postgres://user:pass@localhost/db
DEBUG=true
// main.rs
let config = RuniqueConfig::from_env();
let db = DatabaseConfig::from_env()?.build().connect().await?;