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!
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.
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