{"record":{"id":"6905508453bfab36","repo":"kataras/iris","slug":"django-template-data-should-be-a-map-or-struct","errorCode":null,"errorMessage":"django: template data: should be a map or struct","messagePattern":"django: template data: should be a map or struct","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"view/django.go","lineNumber":302,"sourceCode":"\n// getPongoContext returns the pongo2.Context from map[string]any or from pongo2.Context, used internaly\nfunc getPongoContext(templateData any) pongo2.Context {\n\tif templateData == nil {\n\t\treturn nil\n\t}\n\n\tswitch data := templateData.(type) {\n\tcase pongo2.Context:\n\t\treturn data\n\tcase context.Map:\n\t\treturn pongo2.Context(data)\n\tdefault:\n\t\t// if struct, convert it to map[string]any\n\t\tif structs.IsStruct(data) {\n\t\t\treturn pongo2.Context(structs.Map(data))\n\t\t}\n\n\t\tpanic(\"django: template data: should be a map or struct\")\n\t}\n}\n\nfunc (s *DjangoEngine) fromCache(relativeName string) *pongo2.Template {\n\tif s.reload {\n\t\ts.rmu.RLock()\n\t\tdefer s.rmu.RUnlock()\n\t}\n\n\tif tmpl, ok := s.templateCache[relativeName]; ok {\n\t\treturn tmpl\n\t}\n\treturn nil\n}\n\n// ExecuteWriter executes a templates and write its results to the w writer\n// layout here is useless.\nfunc (s *DjangoEngine) ExecuteWriter(w io.Writer, filename string, _ string, bindingData any) error {","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/view/django.go#L284-L320","documentation":"The django view engine's context converter accepts only map-like values (and structs, via reflection) as template data. When ExecuteWriter receives data of another kind (nil of unexpected type, slice, scalar) it panics with this message because pongo2 has no context representation for it.","triggerScenarios":"ctx.View(\"page.html\", someSlice) or ctx.View(\"page.html\", 42) or ctx.View(\"page.html\", nil-ish non-map non-struct value) — getPongoContext falls through the switch to the default branch and panics.","commonSituations":"Passing a []User list directly instead of wrapping it (map[string]any{\"users\": users}), passing a pointer to a struct wrapped incorrectly, or returning ORM query results that are slices.","solutions":["Wrap non-map data in a map: ctx.View(\"page.html\", map[string]any{\"items\": data}).","Pass structs by value (or as pointer auto-deref supported by structs.IsStruct) so the struct->map branch runs.","If data can be nil, guard before View: pass map[string]any{} instead.","Adjust the template to index into the map key rather than expecting the bare value."],"exampleFix":"// before\nreturn ctx.View(\"list.html\", users) // users is []User -> panic\n// after\nreturn ctx.View(\"list.html\", map[string]any{\"users\": users})","handlingStrategy":"type-guard","validationCode":"func viewData(v any) any {\n\tif v == nil { return map[string]any{} }\n\tswitch v.(type) {\n\tcase map[string]any, map[string]string:\n\t\treturn v\n\tdefault:\n\t\tif reflect.TypeOf(v).Kind() != reflect.Struct {\n\t\t\tpanic(\"view data must be map or struct\")\n\t\t}\n\t\treturn v\n\t}\n}","typeGuard":"func isMapView(v any) bool {\n\tif v == nil { return false }\n\tt := reflect.TypeOf(v)\n\tif t.Kind() == reflect.Ptr { t = t.Elem() }\n\treturn t.Kind() == reflect.Map || t.Kind() == reflect.Struct\n}","tryCatchPattern":"defer func() {\n\tif r := recover(); strings.Contains(fmt.Sprint(r), \"template data\") {\n\t\tlog.Printf(\"bad view data: %v\", r)\n\t}\n}()","preventionTips":["Always wrap slices/scalars: map[string]any{\"key\": val}.","Never pass nil directly to ctx.View; pass an empty map.","Add a lint/test that exercises every template render path."],"tags":["templates","django","panic","wrong-type"],"backgroundTag":"template-data-type-error","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}