I'm sure this is completely wrong. I needed a Django model for testing, but I don't have a Django app or even a Django project. I'm developing a Django model reader for Carousel, and so I needed a model to test it out with. Sure I could have created a quick django project, but that seemed silly, and my first instinct was to import django.db.models
, make a model and use it, but this raised:
ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
Most normal people would turn back now, but instead I imported django.conf.settings
and called settings.configure()
just like it said to do. Now I got this error:
AppRegistryNotReady: Apps aren't loaded yet.
So now I felt like I was getting somewhere. But where? Googling told me to import django
and run setup
which I did and that raised:
RuntimeError: Model class __main__.MyModel doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
Wow! Normally RuntimeError
is a scary warning, like you dumped your core, but this just said I needed to add the app to settings.INSTALLED_APPS
, which makes perfect sense, and it also complained that my model wasn't actually part of an app and even explained how to explicitly declare it. Some more Googling and I discovered that app_label
is a model option that can be set in class Meta
. So I did as told, and it worked!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | from django.db import models from django.conf import settings import django MYAPP = 'myapp.MyApp' settings.configure() django.setup() settings.INSTALLED_APPS.append(MYAPP) class MyModel(models.Model): air_temp = models.FloatField() latitude = models.FloatField() longitude = models.FloatField() timezone = models.FloatField() pvmodule = models.CharField(max_length = 20 ) class Meta: app_label = MYAPP mymodel = MyModel(air_temp = 25.0 , latitude = 38.0 , longitude = - 122.0 , timezone = - 8.0 , pvmodule = 'SPR E20-327' ) mymodel.__dict__ #{'_state': <django.db.models.base.ModelState at 0x496b2b0>, # 'air_temp': 25.0, # 'id': None, # 'latitude': 38.0, # 'longitude': -122.0, # 'pvmodule': 'SPR E20-327', # 'timezone': -8.0} |
Caveats
So I should stop here and point out that that evidently the order of these commands matters, because if I add the fake app to INSTALLED_APPS
before calling django.setup()
then I get this:
ImportError: No module named myapp
And unfortunately, I just figured this out now, in this post. But this isn't what I originally did. Yes, I'm completely crazy. First I added a fake module called 'myapp'
to sys.modules
setting it to a mock object, but that didn't work. I got back TypeError: 'Mock' object is not iterable
because, as I found out later, there has to be an AppConfig
subclass in the app module. But since I didn't know that yet, I did the only logical thing and put the module in a list. What? Yes, did I mention I'm an idiot? This nonsense yielded the following stern warning:
ImproperlyConfigured: The app module [] has no filesystem location, you must configure this app with an AppConfig subclass with a 'path' class attribute.
But this is where I found out about AppConfig
in the Django docs which is covered quite nicely. Following the nice directions, I did as told and subclassed AppConfig
, added path
and also name
which I learned from the docs, monkeypatched my mock module with it, and used the dotted name of the app myapp.MyApp
now. I felt like I was getting closer, since I only got: AttributeError: __name__
which seemed like a problem with my pretend module. Another monkeypatch and we have my final ludicrously ridiculous hack.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | from django.db import models from django.conf import settings import django from django.apps import AppConfig import sys import mock class MyApp(AppConfig): """ Apps subclass ``AppConfig`` and define ``name`` and ``path`` """ path = '.' # path to app name = 'myapp' # name of app # make a mock module with ``__name__`` and ``MyApp`` member myapp_module = mock.Mock(__name__ = 'myapp' , MyApp = MyApp) MYAPP = 'myapp.MyApp' # full path to app sys.modules[ 'myapp' ] = myapp_module # register module settings.configure() settings.INSTALLED_APPS.append(MYAPP) django.setup() class MyModel(models.Model): air_temp = models.FloatField() latitude = models.FloatField() longitude = models.FloatField() timezone = models.FloatField() pvmodule = models.CharField(max_length = 20 ) class Meta: app_label = MYAPP mymodel = MyModel(air_temp = 25.0 , latitude = 38.0 , longitude = - 122.0 , timezone = - 8.0 , pvmodule = 'SPR E20-327' ) mymodel.__dict__ #{'_state': <django.db.models.base.ModelState at 0x496b2b0>, # 'air_temp': 25.0, # 'id': None, # 'latitude': 38.0, # 'longitude': -122.0, # 'pvmodule': 'SPR E20-327', # 'timezone': -8.0} |
Yay?
No comments:
Post a Comment