Keywords: Django migrations | data migration | application dependencies
Abstract: This article provides an in-depth exploration of the common 'No installed app with label' error in Django data migrations, particularly when attempting to access models from built-in applications like django.contrib.admin. By analyzing how Django's migration mechanism works, it explains why models that are accessible in the shell fail during migration execution. The article details how to resolve this issue through proper migration dependency configuration, complete with code examples and best practice recommendations.
Problem Description and Context
Data migration is a common and crucial operation in Django development. Many developers encounter a perplexing error when writing RunPython functions: LookupError: No installed app with label 'admin'. This error typically occurs when attempting to access models from the django.contrib.admin application, even though the app is correctly configured in INSTALLED_APPS.
Root Cause Analysis
To understand this error, it's essential to comprehend how Django's migration mechanism operates. During migration execution, Django creates a special application registry that only includes applications explicitly declared as dependencies. This differs from the full application registry used in the shell or during normal runtime.
In the described scenario, the developer can successfully access the admin.LogEntry model in the shell:
>>> from django.apps import apps
>>> apps.get_model('admin', 'LogEntry')
django.contrib.admin.models.LogEntry
But the same operation fails during migration:
def do_it(apps, schema_editor):
LogEntry = apps.get_model('admin', 'LogEntry') # This raises an exception
Debug output reveals that the application registry during migration is empty:
ipdb> apps.get_apps()
[]
ipdb> apps.all_models.keys()
['website', 'google', 'allauth', ...] # No 'admin' present
Solution: Proper Migration Dependency Configuration
According to Django's official documentation, when a RunPython function needs to use models from other applications, those applications must be explicitly declared in the migration's dependencies attribute. This is a safety feature of Django's migration system that ensures migrations execute in the correct order.
Here's the correct solution:
from django.db import migrations
def move_data(apps, schema_editor):
"""
Data migration function requiring access to admin's LogEntry model
"""
# Now we can safely access the admin application's models
LogEntry = apps.get_model('admin', 'LogEntry')
# Execute data migration logic
# ...
class Migration(migrations.Migration):
"""
Example migration class demonstrating proper dependency configuration
"""
dependencies = [
# Previous migration of the current app
('myapp', '0001_initial'),
# Critical: Add dependency for the admin app
# The specific migration file depends on your Django version
('admin', '0002_logentry_remove_auto_add'),
]
operations = [
migrations.RunPython(move_data),
]
Determining the Correct Dependency Version
To find the latest migration file for the django.contrib.admin application, examine the corresponding directory in Django's source code:
# Django 1.11 and later
$ python -c "import django; print(django.__path__[0] + '/contrib/admin/migrations')"
# Examine migration files in this directory
# Typically the latest migration file will be something like 0002_logentry_remove_auto_add.py
Different Django versions may have different migration files for the admin application. It's recommended to always use the latest migration of the application as a dependency.
Best Practice Recommendations
1. Always Check Migration Dependencies: When writing RunPython functions that involve multiple applications, carefully verify that the dependencies list includes all required applications.
2. Use Correct App Labels: Ensure you're using the actual application label, not the Python import path. For built-in applications, the label is typically the part without the django.contrib. prefix.
3. Test Migrations: Before applying migrations, use python manage.py migrate --plan to check the migration plan and verify all dependencies are correctly configured.
4. Handle Third-Party Applications: For third-party applications, you also need to add appropriate migration dependencies. Check the application's migrations directory to determine the correct version.
Frequently Asked Questions
Q: Why does it work in the shell but not during migration?
A: The shell uses the full application registry, while migrations use a restricted registry containing only explicitly declared dependent applications.
Q: What if I don't know which migration version to use?
A: Check the application's migrations directory and use the latest migration file. Alternatively, omit the version initially and let Django suggest available options when it errors.
Q: Does this error only affect the admin application?
A: No, this error affects all applications that are accessed during migration but not declared in dependencies.
Conclusion
The No installed app with label error in Django migrations is a common pitfall, but it can be easily avoided by properly understanding the migration mechanism and correctly configuring dependencies. The key takeaway is that when accessing models from other applications during migration, those applications must be explicitly declared in the dependencies attribute. This approach not only resolves the immediate problem but also ensures migration reliability and maintainability.