Hi Collin,

Thanks for the hint on get_field(), I had read it, but now I will make sure 
to update it soon :-)

Here is the code of one metaclass:


@classmethod
def post_new(cls, model, attrs):
    set_item_field_names = model._meta.get_all_field_names()
    if not 'item' in set_item_field_names:
        return
    item_model = model._meta.get_field_by_name('item')[0].rel.to

    # model and field are passed through from the add_lazy_relation call.
    # target is guaranteed to be a class, even if passed to add_lazy_relation 
as a string
    def add_passthrough_fields(field, target, model):
        item_field_names = target._meta.get_all_field_names()
        for item_field_name in item_field_names:
            if not item_field_name == 'id' and item_field_name not in 
dir(model):
                if item_field_name in set_item_field_names:
                    raise KeyError('\'{}\' must not be 
overwritten'.format(item_field_name))
                else:
                    setattr(model, item_field_name, 
PassThrough(item_field_name))
        setattr(model, model.TYPE_FIELD_NAME, 
PassThrough(model.TYPE_FIELD_NAME, read_only=True))

    # args = model (the source), field (if applicable), target (foreign key 
reference - string or class)
    add_lazy_relation(model, None, item_model, add_passthrough_fields)


And here is a backtrace. I can even trigger it by running ./manage.py help 
in my virtual env


Traceback (most recent call last):
  File "django_project/manage.py", line 16, in <module>
    execute_from_command_line(sys.argv)
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/core/management/__init__.py",
 
line 385, in execute_from_command_line
    utility.execute()
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/core/management/__init__.py",
 
line 354, in execute
    django.setup()
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/__init__.py",
 
line 21, in setup
    apps.populate(settings.INSTALLED_APPS)
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/apps/registry.py",
 
line 108, in populate
    app_config.import_models(all_models)
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/apps/config.py",
 
line 202, in import_models
    self.models_module = import_module(models_module_name)
  File 
"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py",
 
line 37, in import_module
    __import__(name)
  File 
"/Users/mrigal/dev/my.proj/django_project/proj/md/models/__init__.py", line 
5, in <module>
    from proj.md.models.printers import (
  File 
"/Users/mrigal/dev/my.proj/django_project/proj/md/models/printers.py", line 
6, in <module>
    from proj.md.models.base import (
  File "/Users/mrigal/dev/my.proj/django_project/proj/md/models/base.py", 
line 203, in <module>
    class AbstractmdSetItem(mdUpdateModelMixin, models.Model):
  File "/Users/mrigal/dev/my.proj/django_project/proj/md/models/meta.py", 
line 33, in __new__
    cls.post_new(model, attrs)
  File "/Users/mrigal/dev/my.proj/django_project/proj/md/models/meta.py", 
line 83, in post_new
    set_item_field_names = model._meta.get_all_field_names()
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/db/models/options.py",
 
line 432, in get_all_field_names
    cache = self.init_name_map()
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/db/models/options.py",
 
line 445, in init_name_map
    for f, model in self.get_all_related_m2m_objects_with_model():
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/db/models/options.py",
 
line 563, in get_all_related_m2m_objects_with_model
    cache = self._fill_related_many_to_many_cache()
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/db/models/options.py",
 
line 577, in _fill_related_many_to_many_cache
    for klass in self.apps.get_models():
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/utils/lru_cache.py",
 
line 101, in wrapper
    result = user_function(*args, **kwds)
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/apps/registry.py",
 
line 168, in get_models
    self.check_models_ready()
  File 
"/Users/mrigal/dev/_virtualenvs/dj-1.7/lib/python2.7/site-packages/django/apps/registry.py",
 
line 131, in check_models_ready
    raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

I also wouldn't know what to add to app.ready(), since the models 
themselves import their abstract base classes which include themselves the 
metaclasses.

Best,
Matthieu

On Wednesday, November 26, 2014 2:57:28 PM UTC+1, Collin Anderson wrote:
>
> Hi,
>
> I feel like there's almost always a way to avoid metaclasses.
>
> Have you tried adding your relations in the 
>
 

> signal?
>
> For more context, could you post some of your metaclass code and maybe 
> part of a "AppRegsitryNotReady" traceback or two?
>
> Also, get_field_by_name(name)[0] will be deprecated soon. Use 
> .get_field(name) instead.
>
> Collin
>
>
> On Tuesday, November 25, 2014 7:05:54 AM UTC-5, Matthieu Rigal wrote:
>>
>> Hi guys,
>>
>> I am using a metaclass to standardize how I link two classes, on Django 
>> 1.6. This is done in order to have a generic way of connecting classes 
>> without having to know the name of the fields being linked.
>>
>> Basically, I have in my metaclass '*post_new*' method to get the 'other' 
>> model, using *model._meta.get_field_by_name('item') *I use this 
>> afterward like following *add_lazy_relation(model, None, item_model, 
>> add_passthrough_fields) *
>>
>> I add these PassThrough fields again getting the fields from the meta, 
>> overwriting the getter and the setter.
>>
>> Upgrading to Django 1.7 is impossible with what I'm currently doing. I 
>> get tons of *AppRegistryNotReady* , since it is going through this 
>> post_new method at the very beginning. 
>>
>> Maybe you have a suggestion how I could get around this or which other 
>> methods to call to call later (but not too late, those are metaclasses) in 
>> order to get the list of fields. Maybe some code snippets running on Django 
>> 1.7 and using models with metaclasses could already help.
>>
>> Thanks in advance,
>> Matthieu
>>
>> PS: I know it is a bit uncommon to do so and if you don't need to do so 
>> and use these metaclasses, you shouldn't ;-)
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/c437928e-3149-44c3-8656-8c97bfe2f02a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to