I think the accepted answer is old and needs a refresher in 2023 with the detailed approach.
I had the similar problem where I had to create fixtures for specific models from different apps having specific id's. Moreover I had to create just one fixture for all models. so that we don't have to load individual fixtures rather just one fixture for all models.
I did all of this by creating a custom command that calls the dumpdata
internally for each specific model with the specific ids like the following:
products/models.py
class Product(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits = 5, decimal_places = 2)
reviews/models.py
class Review(models.Model):
title = models.CharField(max_length=200)
text = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
rating = models.PositiveIntegerField(default=0)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
def natural_key(self):
return self.title, self.timestamp
class Response(models.Model):
text = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
And following is the command that creates one fixtures for specific models from different apps with specific id's:
generate_fixture.py
from django.core.management import BaseCommand, call_command
from io import StringIO
import json
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('id', type=int, help='Primary Key Of Product')
def handle(self, *args, **options):
id = options.get('id')
if product := Product.objects.filter(id=id).first():
product_fixture = self.get_fixture('products.Product', str(id))
review_ids = list(
Review.objects.filter(product__id=id).values_list('id',flat=True)
)
review_ids = ','.join([str(review_id) for review_id in review_ids])
review_fixture = self.get_fixture('reviews.Review', review_ids)
output = [json.loads(product_fixture)]
output.extend(json.loads(review_fixture))
with open('model_fixtures.json', "w") as file:
json.dump(output, file)
else:
print(f"Product with id {id} does not exists!")
def get_fixture(self, label, pks):
args = ['dumpdata', '--natural-foreign', '--natural-primary', label]
with StringIO() as buffer:
call_command(*args, pks=pks, stdout=buffer)
data = buffer.getvalue()
return data
Now you can run the command with the id like this:
python manage.py generate_fixture 50
And fixture of the models will be generated in just one fixture file which can be loaded like this:
python manage.py loaddata model_fixtures.json