Hi,
On Wednesday, November 26, 2014 11:45:22 AM UTC-5, Matthieu Rigal wrote:
-- You could try using [f.name for f in _meta.fields] instead of _meta.get_all_field_names(). It won't include ManyToMany, but it's more likely to be available at this point.
Collin
On Wednesday, November 26, 2014 11:45:22 AM UTC-5, Matthieu Rigal wrote:
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 envTraceback (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 thesignal?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,MatthieuPS: 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+unsubscribe@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/9794d04c-02eb-4703-95e7-7e801b4f173b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
No comments:
Post a Comment