django-model-seeder 2.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Christian Garcia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ include LICENSE
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-model-seeder
3
+ Version: 2.6.1
4
+ Summary: A Django library powered by Data Seed PH for generating realistic, synthetic Philippine-based datasets directly into Django models.
5
+ Author-email: "Christian G. Garcia" <iyaniyan03112003@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/christiangarcia0311/django-model-seeder
8
+ Project-URL: Repository, https://github.com/christiangarcia0311/django-model-seeder.git
9
+ Keywords: synthetic-data,database-seeding,testing
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: django
19
+ Requires-Dist: data-seed-ph
20
+ Requires-Dist: pyyaml
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7.0; extra == "dev"
23
+ Requires-Dist: pytest-django>=4.0; extra == "dev"
24
+ Dynamic: license-file
25
+
26
+ ## Django Model Seeder
27
+
28
+ [![GitHub stars](https://img.shields.io/github/stars/christiangarcia0311/django-model-seeder?style=social)](https://github.com/christiangarcia0311/django-model-seeder/stargazers)
29
+ [![GitHub issues](https://img.shields.io/github/issues/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/issues)
30
+ ![Static Badge](https://img.shields.io/badge/License-MIT-orange?style=flat)
31
+ ![Static Badge](https://img.shields.io/badge/Github-django_model_seeder-green?style=flat&logo=github)
32
+ ![Static Badge](https://img.shields.io/badge/Pypi-django_model_seeder-blue?style=flat&logo=pypi&logoColor=white)
33
+ ![Static Badge](https://img.shields.io/badge/Django-5.2+-green?style=flat&logo=django&logoColor=white)
34
+ ![Static Badge](https://img.shields.io/badge/Python-3.9+-blue?style=flat&logo=python&logoColor=white)
35
+ [![Last commit](https://img.shields.io/github/last-commit/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/commits/main)
36
+ [![Latest release](https://img.shields.io/github/v/release/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/releases/latest)
37
+
38
+ **Command-based synthetic data generation and seeding for Django models using [data-seed-ph](https://github.com/christiangarcia0311/data-seed-ph).**
39
+
40
+ >[!NOTE]
41
+ > Designed for rapid database population in development environments, API testing, QA automation, and demo applications with seamless integration to Django's management command system.
42
+
43
+ View full documentation: [Github](https://github.com/christiangarcia0311/django-model-seeder)
44
+
@@ -0,0 +1,19 @@
1
+ ## Django Model Seeder
2
+
3
+ [![GitHub stars](https://img.shields.io/github/stars/christiangarcia0311/django-model-seeder?style=social)](https://github.com/christiangarcia0311/django-model-seeder/stargazers)
4
+ [![GitHub issues](https://img.shields.io/github/issues/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/issues)
5
+ ![Static Badge](https://img.shields.io/badge/License-MIT-orange?style=flat)
6
+ ![Static Badge](https://img.shields.io/badge/Github-django_model_seeder-green?style=flat&logo=github)
7
+ ![Static Badge](https://img.shields.io/badge/Pypi-django_model_seeder-blue?style=flat&logo=pypi&logoColor=white)
8
+ ![Static Badge](https://img.shields.io/badge/Django-5.2+-green?style=flat&logo=django&logoColor=white)
9
+ ![Static Badge](https://img.shields.io/badge/Python-3.9+-blue?style=flat&logo=python&logoColor=white)
10
+ [![Last commit](https://img.shields.io/github/last-commit/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/commits/main)
11
+ [![Latest release](https://img.shields.io/github/v/release/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/releases/latest)
12
+
13
+ **Command-based synthetic data generation and seeding for Django models using [data-seed-ph](https://github.com/christiangarcia0311/data-seed-ph).**
14
+
15
+ >[!NOTE]
16
+ > Designed for rapid database population in development environments, API testing, QA automation, and demo applications with seamless integration to Django's management command system.
17
+
18
+ View full documentation: [Github](https://github.com/christiangarcia0311/django-model-seeder)
19
+
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-model-seeder
3
+ Version: 2.6.1
4
+ Summary: A Django library powered by Data Seed PH for generating realistic, synthetic Philippine-based datasets directly into Django models.
5
+ Author-email: "Christian G. Garcia" <iyaniyan03112003@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/christiangarcia0311/django-model-seeder
8
+ Project-URL: Repository, https://github.com/christiangarcia0311/django-model-seeder.git
9
+ Keywords: synthetic-data,database-seeding,testing
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: django
19
+ Requires-Dist: data-seed-ph
20
+ Requires-Dist: pyyaml
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7.0; extra == "dev"
23
+ Requires-Dist: pytest-django>=4.0; extra == "dev"
24
+ Dynamic: license-file
25
+
26
+ ## Django Model Seeder
27
+
28
+ [![GitHub stars](https://img.shields.io/github/stars/christiangarcia0311/django-model-seeder?style=social)](https://github.com/christiangarcia0311/django-model-seeder/stargazers)
29
+ [![GitHub issues](https://img.shields.io/github/issues/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/issues)
30
+ ![Static Badge](https://img.shields.io/badge/License-MIT-orange?style=flat)
31
+ ![Static Badge](https://img.shields.io/badge/Github-django_model_seeder-green?style=flat&logo=github)
32
+ ![Static Badge](https://img.shields.io/badge/Pypi-django_model_seeder-blue?style=flat&logo=pypi&logoColor=white)
33
+ ![Static Badge](https://img.shields.io/badge/Django-5.2+-green?style=flat&logo=django&logoColor=white)
34
+ ![Static Badge](https://img.shields.io/badge/Python-3.9+-blue?style=flat&logo=python&logoColor=white)
35
+ [![Last commit](https://img.shields.io/github/last-commit/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/commits/main)
36
+ [![Latest release](https://img.shields.io/github/v/release/christiangarcia0311/django-model-seeder?style=flat)](https://github.com/christiangarcia0311/django-model-seeder/releases/latest)
37
+
38
+ **Command-based synthetic data generation and seeding for Django models using [data-seed-ph](https://github.com/christiangarcia0311/data-seed-ph).**
39
+
40
+ >[!NOTE]
41
+ > Designed for rapid database population in development environments, API testing, QA automation, and demo applications with seamless integration to Django's management command system.
42
+
43
+ View full documentation: [Github](https://github.com/christiangarcia0311/django-model-seeder)
44
+
@@ -0,0 +1,18 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ django_model_seeder.egg-info/PKG-INFO
6
+ django_model_seeder.egg-info/SOURCES.txt
7
+ django_model_seeder.egg-info/dependency_links.txt
8
+ django_model_seeder.egg-info/requires.txt
9
+ django_model_seeder.egg-info/top_level.txt
10
+ django_seeder/__init__.py
11
+ django_seeder/config_parser.py
12
+ django_seeder/loaders.py
13
+ django_seeder/seeder.py
14
+ django_seeder/management/__init__.py
15
+ django_seeder/management/commands/__init__.py
16
+ django_seeder/management/commands/clear_seeds.py
17
+ django_seeder/management/commands/list_seeds.py
18
+ django_seeder/management/commands/seed_models.py
@@ -0,0 +1,7 @@
1
+ django
2
+ data-seed-ph
3
+ pyyaml
4
+
5
+ [dev]
6
+ pytest>=7.0
7
+ pytest-django>=4.0
@@ -0,0 +1,19 @@
1
+ '''
2
+ Django Model Seeder
3
+ -------------------
4
+
5
+ A Django library powered by Data Seed PH for generating realistic,
6
+ synthetic Philippine-based datasets directly into Django models
7
+
8
+ Information
9
+ -----------
10
+ @author: Christian G. Garcia
11
+ @github: github.com/christiangarcia0311/django-model-seeder
12
+ '''
13
+
14
+ from .seeder import ModelSeeder
15
+ from .loaders import BulkModelLoader
16
+ from .config_parser import ConfigParser
17
+
18
+ __version__ = '3.1.0'
19
+ __all__ = ['ModelSeeder', 'BulkModelLoader', 'ConfigParser']
@@ -0,0 +1,81 @@
1
+ '''
2
+ Config Parser
3
+
4
+ This module provides utilities for loading, validating, and merging configuration
5
+ files in JSON and YAML formats. It also includes preprocessing logic to convert
6
+ numeric range lists into tuples for easier downstream data handling.
7
+
8
+ Information
9
+ -----------
10
+ @author: Christian G. Garcia
11
+ @github: github.com/christiangarcia/django-model-seeder
12
+ '''
13
+
14
+
15
+ import json
16
+ import yaml
17
+ from pathlib import Path
18
+ from typing import Dict, Any
19
+
20
+
21
+ class ConfigParser:
22
+
23
+ @staticmethod
24
+ def load_json(filepath: str) -> Dict[str, Any]:
25
+ with open(filepath, 'r') as f:
26
+ data = json.load(f)
27
+ return ConfigParser._convert_to_tuples(data)
28
+
29
+ @staticmethod
30
+ def load_yaml(filepath: str) -> Dict[str, Any]:
31
+ with open(filepath, 'r') as f:
32
+ return yaml.safe_load(f)
33
+
34
+ @staticmethod
35
+ def _convert_to_tuples(config: Dict[str, Any]) -> Dict[str, Any]:
36
+ for model_name, model_config in config.items():
37
+ if isinstance(model_config, dict) and 'mapping' in model_config:
38
+ mapping = model_config['mapping']
39
+ for field_name, value in mapping.items():
40
+ if isinstance(value, list) and len(value) >= 2:
41
+ if all(isinstance(v, (int, float)) or v == 'float' for v in value):
42
+ mapping[field_name] = tuple(value)
43
+ return config
44
+
45
+ @staticmethod
46
+ def load_config(filepath: str) -> Dict[str, Any]:
47
+ path = Path(filepath)
48
+
49
+ if path.suffix == '.json':
50
+ return ConfigParser.load_json(filepath)
51
+ elif path.suffix in ['.yaml', '.yml']:
52
+ return ConfigParser.load_yaml(filepath)
53
+ else:
54
+ raise ValueError(f"Unsupported config format: {path.suffix}")
55
+
56
+ @staticmethod
57
+ def validate_config(config: Dict[str, Any]) -> bool:
58
+ if not isinstance(config, dict):
59
+ return False
60
+
61
+ for model_name, model_config in config.items():
62
+ if not isinstance(model_config, dict):
63
+ return False
64
+ if 'rows' not in model_config or 'mapping' not in model_config:
65
+ return False
66
+ if not isinstance(model_config['mapping'], dict):
67
+ return False
68
+
69
+ return True
70
+
71
+ @staticmethod
72
+ def merge_configs(base_config: Dict[str, Any], override_config: Dict[str, Any]) -> Dict[str, Any]:
73
+ merged = base_config.copy()
74
+
75
+ for model_name, model_config in override_config.items():
76
+ if model_name in merged:
77
+ merged[model_name].update(model_config)
78
+ else:
79
+ merged[model_name] = model_config
80
+
81
+ return merged
@@ -0,0 +1,84 @@
1
+ '''
2
+ Loaders module
3
+
4
+ Provides a bulk loader utility for registering Django models and
5
+ executing seed operations using ModelSeeder instances
6
+
7
+ Information
8
+ -----------
9
+ @author: Christian G. Garcia
10
+ @github: github.com/christiangarcia0311/django-model-seeder
11
+ '''
12
+
13
+ from django.apps import apps
14
+ from django.db.models import Model
15
+ from typing import Dict, List, Type, Any, Callable
16
+ from .seeder import ModelSeeder
17
+
18
+
19
+ class BulkModelLoader:
20
+
21
+ def __init__(self):
22
+ self.seeders = {}
23
+ self.results = {}
24
+
25
+ def register(self, model: Type[Model])-> ModelSeeder:
26
+ seeder = ModelSeeder(model)
27
+ self.seeders[model.__name__] = seeder
28
+ return seeder
29
+
30
+ def load_model(self, app_label: str, model_name: str) -> ModelSeeder:
31
+ model = apps.get_model(app_label, model_name)
32
+ return self.register(model)
33
+
34
+ def seed_all(
35
+ self,
36
+ configurations: Dict[str, Dict[str, Any]],
37
+ relations_map: Dict[str, Dict[str, Callable]] = None
38
+ ) -> Dict[str, List[Model]]:
39
+
40
+ relations_map = relations_map or {}
41
+ results = {}
42
+
43
+ for model_name, config in configurations.items():
44
+ if model_name in self.seeders:
45
+ seeder = self.seeders[model_name]
46
+ rows = config.get('rows', 10)
47
+ mapping = config.get('mapping', {})
48
+ relations = relations_map.get(model_name, {})
49
+
50
+ if relations:
51
+ results[model_name] = seeder.seed_with_relations(rows, mapping, relations)
52
+ else:
53
+ results[model_name] = seeder.seed(rows, mapping)
54
+
55
+ self.results[model_name] = results[model_name]
56
+
57
+ return results
58
+
59
+ def seed_model(self, model_name: str, rows: int, mapping: Dict[str, Any]) -> List[Model]:
60
+ if model_name in self.seeders:
61
+ result = self.seeders[model_name].seed(rows, mapping, relations_map=None)
62
+ self.results[model_name] = result
63
+ return result
64
+ return []
65
+
66
+ def get_results(self, model_name: str = None) -> Dict[str, List[Model]] | List[Model]:
67
+ if model_name:
68
+ return self.results.get(model_name, [])
69
+ return self.results
70
+
71
+ def clear(self, model_name: str = None):
72
+ if model_name and model_name in self.seeders:
73
+ self.seeders[model_name].model.objects.all().delete()
74
+
75
+ if model_name in self.results:
76
+ del self.results[model_name]
77
+ else:
78
+ for seeder in self.seeders.values():
79
+ seeder.model.objects.all().delete()
80
+ self.results.clear()
81
+
82
+ def list_models(self) -> List[str]:
83
+ return list(self.seeders.keys())
84
+
@@ -0,0 +1,76 @@
1
+ '''
2
+ Clear command
3
+
4
+ This management command provides utilities to delete (clear) seeded or existing
5
+ data from Django models. It supports clearing a specific model or all models
6
+ across all installed apps, with optional confirmation prompts for safety.
7
+ '''
8
+
9
+ from django.core.management.base import BaseCommand, CommandError
10
+ from django.apps import apps
11
+
12
+
13
+ class Command(BaseCommand):
14
+ help = 'Clear seeded data from Django models'
15
+
16
+ def add_arguments(self, parser):
17
+ parser.add_argument(
18
+ '--model',
19
+ type=str,
20
+ help='Specific model to clear (format: ModelName)'
21
+ )
22
+
23
+ parser.add_argument(
24
+ '--app',
25
+ type=str,
26
+ help='Django app label'
27
+ )
28
+
29
+ parser.add_argument(
30
+ '--all',
31
+ action='store_true',
32
+ help='Clear all data from all models (dangerous)'
33
+ )
34
+
35
+ parser.add_argument(
36
+ '--confirm',
37
+ action='store_true',
38
+ help='Skip confirmation prompt'
39
+ )
40
+
41
+ def handle(self, *args, **options):
42
+ if options['all']:
43
+ if not options['confirm']:
44
+ confirm = input('Clear ALL data from ALL models? (yes/no): ')
45
+ if confirm.lower() != 'yes':
46
+ self.stdout.write('Aborted')
47
+ return
48
+
49
+ count = 0
50
+ for app_config in apps.get_app_configs():
51
+ for model in app_config.get_models():
52
+ deleted, _ = model.objects.all().delete()
53
+ count += deleted
54
+ self.stdout.write(f'Cleared {model.__name__}')
55
+
56
+ self.stdout.write(self.style.SUCCESS(f'Total records deleted: {count}'))
57
+
58
+ elif options['model'] and options['app']:
59
+ try:
60
+ model = apps.get_model(options['app'], options['model'])
61
+ count = model.objects.count()
62
+
63
+ if not options['confirm']:
64
+ confirm = input(f'Clear {count} records from {options["model"]}? (yes/no): ')
65
+ if confirm.lower() != 'yes':
66
+ self.stdout.write('Aborted')
67
+ return
68
+
69
+ model.objects.all().delete()
70
+ self.stdout.write(self.style.SUCCESS(f'Cleared {options["model"]}'))
71
+ except LookupError:
72
+ raise CommandError(f'Model not found: {options["app"]}.{options["model"]}')
73
+ else:
74
+ self.stdout.write(
75
+ self.style.ERROR('Either --all or both --model and --app must be provided')
76
+ )
@@ -0,0 +1,61 @@
1
+ '''
2
+ List command
3
+
4
+
5
+ This management command lists all available Django models that can be used
6
+ for seeding or data operations. It supports filtering by app and optionally
7
+ displaying record counts for each model.
8
+ '''
9
+
10
+ from django.core.management.base import BaseCommand, CommandError
11
+ from django.apps import apps
12
+
13
+
14
+ class Command(BaseCommand):
15
+
16
+ help = 'List all available Django models for seeding'
17
+
18
+ def add_arguments(self, parser):
19
+ parser.add_argument(
20
+ '--app',
21
+ type=str,
22
+ default=None,
23
+ help='Filter by specific app label name'
24
+ )
25
+ parser.add_argument(
26
+ '--count',
27
+ action='store_true',
28
+ help='Show record count each model'
29
+ )
30
+
31
+ def handle(self, *args, **options):
32
+ app_name_filter = options.get('app')
33
+ show_record_count = options.get('count', False)
34
+
35
+ self.stdout.write(
36
+ self.style.SUCCESS('Available for seeding:\n')
37
+ )
38
+
39
+ for app_config in apps.get_app_configs():
40
+ if app_name_filter and app_config.label != app_name_filter:
41
+ continue
42
+
43
+ models = app_config.get_models()
44
+
45
+ if models:
46
+ self.stdout.write(
47
+ self.style.WARNING(f'{app_config.label}: ')
48
+ )
49
+
50
+ for model in models:
51
+ model_name = model.__name__
52
+ count = model.objects.count() if show_record_count else None
53
+
54
+ if show_record_count:
55
+ self.stdout.write(
56
+ f'{model_name} ({count} records)'
57
+ )
58
+ else:
59
+ self.stdout.write(f'{model_name}')
60
+ self.stdout.write('')
61
+
@@ -0,0 +1,196 @@
1
+ '''
2
+ Seed command
3
+
4
+
5
+ This management command seeds Django models with synthetic data using a configurable
6
+ mapping system. It supports JSON/YAML configuration files, direct model targeting,
7
+ data clearing, dry-run previews, and relational data seeding.
8
+ '''
9
+
10
+
11
+
12
+ from django.core.management.base import BaseCommand, CommandError
13
+ from django.apps import apps
14
+ from django_seeder import BulkModelLoader, ConfigParser
15
+
16
+
17
+ class Command(BaseCommand):
18
+
19
+ help = 'Seed Django models with synthetic data'
20
+
21
+ def add_arguments(self, parser):
22
+ parser.add_argument(
23
+ '--config',
24
+ type=str,
25
+ default=None,
26
+ help='Path to seed configuration file (JSON or YAML)'
27
+ )
28
+ parser.add_argument(
29
+ '--model',
30
+ type=str,
31
+ default=None,
32
+ help='Seed specific model (format: app_label.ModelName)'
33
+ )
34
+ parser.add_argument(
35
+ '--rows',
36
+ type=int,
37
+ default=10,
38
+ help='Number of rows to seed (default: 10)'
39
+ )
40
+ parser.add_argument(
41
+ '--app',
42
+ type=str,
43
+ default=None,
44
+ help='Django app label name'
45
+ )
46
+ parser.add_argument(
47
+ '--clear',
48
+ action='store_true',
49
+ help='Clear existing data in models before seeding'
50
+ )
51
+ parser.add_argument(
52
+ '--dry-run',
53
+ action='store_true',
54
+ help='Show what would be seeded without actually seeding'
55
+ )
56
+ parser.add_argument(
57
+ '--verbose',
58
+ action='store_true',
59
+ help='Show detailed output'
60
+ )
61
+
62
+ def handle(self, *args, **options):
63
+ loader = BulkModelLoader()
64
+ config = None
65
+
66
+ if options['config']:
67
+ try:
68
+ config = ConfigParser.load_config(options['config'])
69
+
70
+ if not ConfigParser.validate_config(config):
71
+ raise CommandError('Invalid file configuration format')
72
+
73
+ for model_name in config.keys():
74
+ try:
75
+ app_label = config[model_name].get('app_label', 'core')
76
+ model = apps.get_model(app_label, model_name)
77
+ loader.register(model)
78
+ except LookupError:
79
+ raise CommandError(f'Model not found: {app_label}.{model_name}')
80
+
81
+ self.stdout.write(
82
+ self.style.SUCCESS(f'Loaded config from {options["config"]}')
83
+ )
84
+ except FileNotFoundError:
85
+ raise CommandError(f'Configuration file not found: {options["config"]}')
86
+ except Exception as e:
87
+ raise CommandError(f'Error loading config: {str(e)}')
88
+
89
+ elif options['model'] and options['app']:
90
+ app_label = options['app']
91
+ model_name = options['model']
92
+ rows = options['rows']
93
+
94
+ try:
95
+ model = apps.get_model(app_label, model_name)
96
+ loader.register(model)
97
+
98
+ config = {
99
+ model_name: {
100
+ 'rows': rows,
101
+ 'mapping': self._get_default_mapping(model)
102
+ }
103
+ }
104
+
105
+ self.stdout.write(
106
+ self.style.WARNING(
107
+ f'No mapping provided. Using auto-detected fields for {model_name}'
108
+ )
109
+ )
110
+ except LookupError:
111
+ raise CommandError(f'Model not found: {app_label}.{model_name}')
112
+
113
+ else:
114
+ raise CommandError('Either --config or both --model and --app must be provided')
115
+
116
+ if not config:
117
+ raise CommandError('No configuration available')
118
+
119
+ if options['clear']:
120
+ self.stdout.write(
121
+ self.style.WARNING('Clearing existing data...')
122
+ )
123
+
124
+ for model_name in loader.seeders:
125
+ loader.clear(model_name)
126
+
127
+ self.stdout.write(
128
+ self.style.SUCCESS('Data successfully cleared')
129
+ )
130
+
131
+ if options['dry_run']:
132
+ self.stdout.write(
133
+ self.style.WARNING('DRY RUN MODE')
134
+ )
135
+
136
+ for model_name, model_config in config.items():
137
+ rows = model_config.get('rows', 10)
138
+
139
+ self.stdout.write(
140
+ f' Would seed {rows} rows in {model_name}'
141
+ )
142
+ return
143
+
144
+ try:
145
+ results = {}
146
+
147
+ for model_name, model_config in config.items():
148
+ seeder = loader.seeders[model_name]
149
+ rows = model_config.get('rows', 10)
150
+ mapping = model_config.get('mapping', {})
151
+ relations = model_config.get('relations', {})
152
+
153
+ if relations:
154
+ relation_resolvers = {}
155
+ for rel_field, rel_model_name in relations.items():
156
+ if rel_model_name in results:
157
+ instances = results[rel_model_name]
158
+ relation_resolvers[rel_field] = lambda: instances[__import__('random').randint(0, len(instances) - 1)]
159
+
160
+ result = seeder.seed_with_relations(rows, mapping, relation_resolvers)
161
+ else:
162
+ result = seeder.seed(rows, mapping)
163
+
164
+ results[model_name] = result
165
+
166
+ self.stdout.write(
167
+ self.style.SUCCESS('Seeding successfully completed')
168
+ )
169
+
170
+ for model_name, instances in results.items():
171
+ self.stdout.write(
172
+ f'{model_name}: {len(instances)} rows seeded'
173
+ )
174
+
175
+ if options['verbose']:
176
+ self.stdout.write('\nDetailed Results')
177
+
178
+ for model_name, instances in results.items():
179
+ self.stdout.write(f'\n{model_name}')
180
+
181
+ for index, instance in enumerate(instances[:3], 1):
182
+ self.stdout.write(f' {index}. {instance}')
183
+
184
+ if len(instances) > 3:
185
+ self.stdout.write(f' ... and {len(instances) - 3} more')
186
+
187
+ except Exception as e:
188
+ raise CommandError(f'Error during seeding: {str(e)}')
189
+
190
+ def _get_default_mapping(self, model):
191
+ mapping = {}
192
+ for field in model._meta.get_fields():
193
+ if field.many_to_one or field.one_to_one or field.many_to_many:
194
+ continue
195
+ mapping[field.name] = field.name
196
+ return mapping
@@ -0,0 +1,113 @@
1
+ '''
2
+ Seeder Module
3
+
4
+ This module provides the core functionality for generating and inserting
5
+ synthetic data into Django models. It is designed to simplify database
6
+ seeding during development and testing by automatically generating
7
+ structured datasets and converting them into Django ORM model instances.
8
+
9
+ Information
10
+ -----------
11
+ @author: Christian G. Garcia
12
+ @github: github.com/christiangarcia0311/django-model-seeder
13
+ '''
14
+
15
+
16
+ from seed import Dataset
17
+ from django.db.models import Model
18
+ from typing import Dict, List, Type, Any, Callable
19
+
20
+
21
+ class ModelSeeder:
22
+
23
+ def __init__(self, model: Type[Model]):
24
+ self.model = model
25
+ self.dataset = Dataset()
26
+ self.field_mapping = {}
27
+
28
+ self._introspect_fields()
29
+
30
+ def _introspect_fields(self):
31
+ for field in self.model._meta.get_fields():
32
+ if field.many_to_one or field.one_to_one:
33
+ continue
34
+
35
+ self.field_mapping[field.name] = None
36
+
37
+ def seed(self, rows: int, mapping: Dict[str, Any]) -> List[Model]:
38
+ data_generator = self.dataset.generate(rows, mapping)
39
+
40
+ instances = []
41
+
42
+ for index, row in data_generator.iterrows():
43
+ kwargs = {}
44
+
45
+ for field_name, value in row.to_dict().items():
46
+ if field_name in self.field_mapping:
47
+ kwargs[field_name] = value
48
+
49
+ instance = self.model(**kwargs)
50
+ instances.append(instance)
51
+
52
+ self.model.objects.bulk_create(instances)
53
+ return instances
54
+
55
+ def seed_with_relations(
56
+ self,
57
+ rows: int,
58
+ mapping: Dict[str, Any],
59
+ relations: Dict[str, Callable] = None
60
+ ) -> List[Model]:
61
+ data_generator = self.dataset.generate(rows, mapping)
62
+
63
+ instances = []
64
+
65
+ for index, row in data_generator.iterrows():
66
+ kwargs = {}
67
+
68
+ for field_name, value in row.to_dict().items():
69
+ if field_name in self.field_mapping:
70
+ kwargs[field_name] = value
71
+
72
+ if relations:
73
+ for relation_field, resolver_func in relations.items():
74
+ try:
75
+ kwargs[relation_field] = resolver_func()
76
+ except Exception as e:
77
+ print(f'Warning: Could not resolve relation {relation_field}: {e}')
78
+ continue
79
+
80
+ instance = self.model(**kwargs)
81
+ instances.append(instance)
82
+
83
+ self.model.objects.bulk_create(instances)
84
+ return instances
85
+
86
+ def seed_with_validation(
87
+ self,
88
+ rows: int,
89
+ mapping: Dict[str, Any],
90
+ validator: Callable = None
91
+ ) -> List[Model]:
92
+ data_generator = self.dataset.generate(rows, mapping)
93
+
94
+ instances = []
95
+
96
+ for index, row in data_generator.iterrows():
97
+ kwargs = {}
98
+
99
+ for field_name, value in row.to_dict().items():
100
+ if field_name in self.field_mapping:
101
+ kwargs[field_name] = value
102
+
103
+ if validator and not validator(kwargs):
104
+ continue
105
+
106
+ instance = self.model(**kwargs)
107
+ instances.append(instance)
108
+
109
+ self.model.objects.bulk_create(instances)
110
+ return instances
111
+
112
+
113
+
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "django-model-seeder"
7
+ version = "2.6.1"
8
+ description = "A Django library powered by Data Seed PH for generating realistic, synthetic Philippine-based datasets directly into Django models."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ authors = [{name = "Christian G. Garcia", email = "iyaniyan03112003@gmail.com"}]
13
+ dependencies = [
14
+ "django",
15
+ "data-seed-ph",
16
+ "pyyaml",
17
+ ]
18
+ keywords = ["synthetic-data", "database-seeding", "testing"]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ ]
26
+
27
+ [project.optional-dependencies]
28
+ dev = [
29
+ "pytest>=7.0",
30
+ "pytest-django>=4.0",
31
+ ]
32
+
33
+ [project.urls]
34
+ Homepage = "https://github.com/christiangarcia0311/django-model-seeder"
35
+ Repository = "https://github.com/christiangarcia0311/django-model-seeder.git"
36
+
37
+ [tool.setuptools.packages.find]
38
+ where = ["."]
39
+ include = ["django_seeder*"]
40
+ exclude = ["fixtures*", "tests*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+