diff --git a/uffd/default_config.cfg b/uffd/default_config.cfg
index 91d665ff778a3c1fc3c393b8a6459aa989c1bb37..619b5fe8ca0ae8b220eb3f1d51abc7c6ab00503f 100644
--- a/uffd/default_config.cfg
+++ b/uffd/default_config.cfg
@@ -15,8 +15,11 @@ LDAP_USER_MAIL_ATTRIBUTE="mail"
 LDAP_USER_MAIL_ALIASES=[]
 LDAP_USER_DEFAULT_ATTRIBUTES={
 	"sn": " ",
+	# All string values are subject to python str.format-style format expansion. To insert literal braces use "{{" and "}}".
+	# Variables: uid, loginname, displayname, mail and possibly other attributes of the User class
 	"homeDirectory": "/home/{loginname}",
-	"gidNumber": LDAP_USER_GID
+	"gidNumber": LDAP_USER_GID,
+	# "multiValueAttribute": ["value1", "value2"],
 }
 
 LDAP_GROUP_SEARCH_BASE="ou=groups,dc=example,dc=com"
diff --git a/uffd/user/models.py b/uffd/user/models.py
index 40a829c3851b31dbe915b755cdcc73b710e96788..8f839add8eadea0290adef3eb262e8942ec1eb16 100644
--- a/uffd/user/models.py
+++ b/uffd/user/models.py
@@ -17,13 +17,18 @@ def get_next_uid():
 		raise Exception('No free uid found')
 	return next_uid
 
-class DictView:
+class ObjectAttributeDict:
 	def __init__(self, obj):
 		self.obj = obj
 
 	def __getitem__(self, key):
 		return getattr(self.obj, key)
 
+def format_with_attributes(fmtstr, obj):
+	# Do str.format-style string formatting with the attributes of an object
+	# E.g. format_with_attributes("/home/{loginname}", obj) = "/home/foobar" if obj.loginname = "foobar"
+	return fmtstr.format_map(ObjectAttributeDict(obj))
+
 class BaseUser(ldap.Model):
 	ldap_search_base = lazyconfig_str('LDAP_USER_SEARCH_BASE')
 	ldap_filter_params = lazyconfig_list('LDAP_USER_SEARCH_FILTER')
@@ -40,19 +45,18 @@ class BaseUser(ldap.Model):
 	groups = [] # Shuts up pylint, overwritten by back-reference
 	roles = [] # Shuts up pylint, overwritten by back-reference
 
-	def dummy_attribute_defaults(self):
-		for name, patterns in current_app.config['LDAP_USER_DEFAULT_ATTRIBUTES'].items():
-			if not isinstance(patterns, list):
-				patterns = [patterns]
-			values = []
-			for pattern in patterns:
-				if isinstance(pattern, str):
-					values.append(pattern.format_map(DictView(self)))
-				else:
-					values.append(pattern)
-			self.ldap_object.setattr(name, values)
-
-	ldap_add_hooks = ldap.Model.ldap_add_hooks + (dummy_attribute_defaults,)
+	def add_default_attributes(self):
+		for name, values in current_app.config['LDAP_USER_DEFAULT_ATTRIBUTES'].items():
+			if not isinstance(values, list):
+				values = [values]
+			formatted_values = []
+			for value in values:
+				if isinstance(value, str):
+					value = format_with_attributes(value, self)
+				formatted_values.append(value)
+			self.ldap_object.setattr(name, formatted_values)
+
+	ldap_add_hooks = ldap.Model.ldap_add_hooks + (add_default_attributes,)
 
 	# Write-only property
 	def password(self, value):