Configuration
This section describes how to configure django-simple-dms.
Required Configuration
Database Configuration
django-simple-dms requires PostgreSQL as it uses PostgreSQL-specific features:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'your_database_name',
'USER': 'your_database_user',
'PASSWORD': 'your_database_password',
'HOST': 'localhost',
'PORT': '5432',
}
}
INSTALLED_APPS
Add django_simple_dms to your INSTALLED_APPS:
INSTALLED_APPS = [
...
'django_simple_dms',
...
]
File Storage Configuration
Storage Backend
By default, the document FileField on the Document model uses Django's default storage backend. You can configure a custom storage backend by setting DMS_DOCUMENT_STORAGE in your Django settings:
# settings.py
# Option 1: Dotted path to a storage class (will be instantiated automatically)
DMS_DOCUMENT_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# Option 2: Callable that returns a storage instance (for custom configuration)
DMS_DOCUMENT_STORAGE = lambda: S3Boto3Storage(bucket_name='my-documents')
# Option 3: Pre-configured storage instance
from storages.backends.s3boto3 import S3Boto3Storage
DMS_DOCUMENT_STORAGE = S3Boto3Storage(bucket_name='my-documents')
If DMS_DOCUMENT_STORAGE is not set, Django's default storage will be used (typically FileSystemStorage saving to MEDIA_ROOT).
Upload Path
By default, documents are uploaded to documents/%Y/%m/%d (e.g., documents/2024/03/15/). This is configured in the Document model's FileField:
document = models.FileField(upload_to='documents/%Y/%m/%d')
Customizing Upload Path
To customize the upload path, you can override the Document model or configure Django's media settings:
# settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Custom Upload Path Function
If you need more control over file upload paths, you can extend the Document model and provide a custom upload_to callable:
from django_simple_dms.models import Document as BaseDocument
def custom_upload_to(instance, filename):
# Custom logic here
# Example: organize by admin user
if instance.admin:
return f'documents/{instance.admin.username}/{filename}'
return f'documents/unassigned/{filename}'
class Document(BaseDocument):
document = models.FileField(upload_to=custom_upload_to)
class Meta:
proxy = True # Use proxy model if you don't want to alter DB schema
User Model Configuration
django-simple-dms uses Django's configurable user model system via get_user_model(). If you're using a custom user model, ensure it's properly configured:
# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
Admin Configuration
The Django admin integration is automatically registered when you add django_simple_dms to INSTALLED_APPS. No additional configuration is needed.
Customizing Admin
To customize the admin interface, you can unregister the default admin and register your own:
# admin.py
from django.contrib import admin
from django_simple_dms.models import Document, DocumentTag
from django_simple_dms.admin import DocumentAdmin, DocumentTagAdmin
# Unregister default
admin.site.unregister(Document)
# Register custom
@admin.register(Document)
class CustomDocumentAdmin(DocumentAdmin):
list_display = ('document', 'admin', 'upload_date', 'reference_period', 'custom_field')
# Add your customizations
Security Considerations
Permission Validation
The permission system is enforced at the model level. When using Document.add(), permission checks are automatically performed. However, if you're creating documents directly via the ORM, you should manually check permissions:
from django_simple_dms.models import Document, TagGrant
from django_simple_dms.exceptions import ForbiddenException
# Check if user can create with tags
check_result = TagGrant.objects.check_create(user, tags=['sensitive.data'])
if isinstance(check_result, CreationCheckFail):
raise ForbiddenException(f"Cannot create with tags: {check_result.tags}")
Superuser Bypass
Superusers automatically bypass all permission checks. Be mindful when granting superuser status:
# Superusers always pass permission checks
if user.is_superuser:
# No TagGrant checks performed
doc = Document.add(document=file, actor=user, tags=any_tags)
PostgreSQL Version Considerations
Django 5.0+ with PostgreSQL 15+
With Django 5.0+ and PostgreSQL 15+, unique constraints use nulls_distinct=False, meaning NULL values are treated as equal for uniqueness:
# Django 5.0+
constraints = [
UniqueConstraint(
name='unique_doc_grant',
fields=['grantor', 'user', 'group', 'document'],
nulls_distinct=False
)
]
Earlier Versions
For Django < 5.0 or PostgreSQL < 15, uniqueness with NULL values is enforced programmatically in the model's save() method.
Development Settings Example
Here's a complete example for development:
# settings.py
DEBUG = True
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_simple_dms',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'dms_dev',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'localhost',
'PORT': '5432',
}
}
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
# Use default settings or customize as needed