Skip to content

Commit 6869166

Browse files
CopilotArchmonger
andauthored
Add Django Signals support for backup and restore operations (#614)
This PR implements Django Signals support for the django-dbbackup package, allowing users to hook into backup and restore operations for both database and media files. The implementation adds 8 new signals that are sent before and after each operation type. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: Archmonger <[email protected]>
1 parent 29fef88 commit 6869166

File tree

10 files changed

+725
-0
lines changed

10 files changed

+725
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Don't forget to remove deprecated code on each major release!
1818

1919
- Implement new `SqliteBackupConnector` to backup SQLite3 databases using the `.backup` command (safe to execute on databases with active connections).
2020
- Verified full Windows compatibility via new CI workflows.
21+
- Add Django Signals support for backup and restore operations. New signals include `pre_backup`, `post_backup`, `pre_restore`, `post_restore`, `pre_media_backup`, `post_media_backup`, `pre_media_restore`, and `post_media_restore`.
2122

2223
### Changed
2324

dbbackup/management/commands/dbbackup.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from ... import settings, utils
88
from ...db.base import get_connector
9+
from ...signals import pre_backup, post_backup
910
from ...storage import StorageError, get_storage
1011
from ._base import BaseDbBackupCommand, make_option
1112

@@ -115,6 +116,15 @@ def _save_new_backup(self, database):
115116
Save a new backup file.
116117
"""
117118
self.logger.info("Backing Up Database: %s", database["NAME"])
119+
120+
# Send pre_backup signal
121+
pre_backup.send(
122+
sender=self.__class__,
123+
database=database,
124+
connector=self.connector,
125+
servername=self.servername,
126+
)
127+
118128
# Get backup, schema and name
119129
filename = self.connector.generate_filename(self.servername)
120130

@@ -146,3 +156,13 @@ def _save_new_backup(self, database):
146156
self.write_to_storage(outputfile, self.path)
147157
else:
148158
self.write_local_file(outputfile, self.path)
159+
160+
# Send post_backup signal
161+
post_backup.send(
162+
sender=self.__class__,
163+
database=database,
164+
connector=self.connector,
165+
servername=self.servername,
166+
filename=filename,
167+
storage=self.storage,
168+
)

dbbackup/management/commands/dbrestore.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
"""
44

55
import io
6+
67
from django.conf import settings
78
from django.core.management.base import CommandError
89
from django.db import connection
910

1011
from ... import utils
1112
from ...db.base import get_connector
13+
from ...signals import post_restore, pre_restore
1214
from ...storage import StorageError, get_storage
1315
from ._base import BaseDbBackupCommand, make_option
1416

@@ -18,6 +20,9 @@ class Command(BaseDbBackupCommand):
1820
content_type = "db"
1921
no_drop = False
2022
pg_options = ""
23+
input_database_name = None
24+
database_name = None
25+
database = None
2126

2227
option_list = BaseDbBackupCommand.option_list + (
2328
make_option("-d", "--database", help="Database to restore"),
@@ -118,6 +123,16 @@ def _restore_backup(self):
118123

119124
self.logger.info(f"Restoring: {input_filename}")
120125

126+
# Send pre_restore signal
127+
pre_restore.send(
128+
sender=self.__class__,
129+
database=self.database,
130+
database_name=self.database_name,
131+
filename=input_filename,
132+
servername=self.servername,
133+
storage=self.storage,
134+
)
135+
121136
if self.decrypt:
122137
unencrypted_file, input_filename = utils.unencrypt_file(input_file, input_filename, self.passphrase)
123138
input_file.close()
@@ -153,3 +168,14 @@ def _restore_backup(self):
153168
self.connector.drop = not self.no_drop
154169
self.connector.pg_options = self.pg_options
155170
self.connector.restore_dump(input_file)
171+
172+
# Send post_restore signal
173+
post_restore.send(
174+
sender=self.__class__,
175+
database=self.database,
176+
database_name=self.database_name,
177+
filename=input_filename,
178+
servername=self.servername,
179+
connector=self.connector,
180+
storage=self.storage,
181+
)

dbbackup/management/commands/mediabackup.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.core.management.base import CommandError
99

1010
from ... import utils
11+
from ...signals import pre_media_backup, post_media_backup
1112
from ...storage import StorageError, get_storage, get_storage_class
1213
from ._base import BaseDbBackupCommand, make_option
1314

@@ -104,6 +105,13 @@ def backup_mediafiles(self):
104105
"""
105106
Create backup file and write it to storage.
106107
"""
108+
# Send pre_media_backup signal
109+
pre_media_backup.send(
110+
sender=self.__class__,
111+
servername=self.servername,
112+
storage=self.storage,
113+
)
114+
107115
# Check for filename option
108116
if self.filename:
109117
filename = self.filename
@@ -127,3 +135,11 @@ def backup_mediafiles(self):
127135
self.write_to_storage(tarball, self.path)
128136
else:
129137
self.write_local_file(tarball, self.path)
138+
139+
# Send post_media_backup signal
140+
post_media_backup.send(
141+
sender=self.__class__,
142+
filename=filename,
143+
servername=self.servername,
144+
storage=self.storage,
145+
)

dbbackup/management/commands/mediarestore.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import tarfile
66

77
from ... import utils
8+
from ...signals import pre_media_restore, post_media_restore
89
from ...storage import get_storage, get_storage_class
910
from ._base import BaseDbBackupCommand, make_option
1011

@@ -79,6 +80,14 @@ def _restore_backup(self):
7980
input_filename, input_file = self._get_backup_file(servername=self.servername)
8081
self.logger.info("Restoring: %s", input_filename)
8182

83+
# Send pre_media_restore signal
84+
pre_media_restore.send(
85+
sender=self.__class__,
86+
filename=input_filename,
87+
servername=self.servername,
88+
storage=self.storage,
89+
)
90+
8291
if self.decrypt:
8392
unencrypted_file, input_filename = utils.unencrypt_file(input_file, input_filename, self.passphrase)
8493
input_file.close()
@@ -103,3 +112,11 @@ def _restore_backup(self):
103112
continue # Skip directories
104113
name = media_file_info.path
105114
self._upload_file(name, media_file)
115+
116+
# Send post_media_restore signal
117+
post_media_restore.send(
118+
sender=self.__class__,
119+
filename=input_filename,
120+
servername=self.servername,
121+
storage=self.storage,
122+
)

dbbackup/signals.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""
2+
Django signals for dbbackup operations.
3+
4+
These signals allow users to hook into the backup and restore process
5+
to perform custom actions before and after backup/restore operations.
6+
"""
7+
8+
import django.dispatch
9+
10+
# Database backup signals
11+
pre_backup = django.dispatch.Signal()
12+
post_backup = django.dispatch.Signal()
13+
14+
# Database restore signals
15+
pre_restore = django.dispatch.Signal()
16+
post_restore = django.dispatch.Signal()
17+
18+
# Media backup signals
19+
pre_media_backup = django.dispatch.Signal()
20+
post_media_backup = django.dispatch.Signal()
21+
22+
# Media restore signals
23+
pre_media_restore = django.dispatch.Signal()
24+
post_media_restore = django.dispatch.Signal()

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ nav:
66
- Databases: databases.md
77
- Storage: storage.md
88
- Commands: commands.md
9+
- Signals: signals.md
910
- Integration: integration.md
1011
- About:
1112
- Changelog: changelog.md

docs/src/dictionary.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ dumpable
4040
schemas
4141
redistributions
4242
whitespace
43+
pre
44+
post

0 commit comments

Comments
 (0)