Roman Akopov
2017-09-05 10:47:37 UTC
Hello,
My problem is very rare so I'll try ad add as much useful detail as
possible.
I am using python 3.5 and 3.6, Django 1.11.4
I am creating complex security related application and need to generate
additional models based on other applications' models. In general,
everything works fine, models are created, migrated without a problem. But
there is single problem I totally failed to solve.
Let's say there is preexisting model Alpha of some other application and I
dynamically create model Beta which references Alpha with ForeignKey. The
problem is that Beta does not get reverse relation, so I can query for
beta.alpha, but not for alpha.betas. I receive
"django.core.exceptions.FieldError: Cannot resolve keyword 'betas' into
field. Choices are: x, y, z"
Here is my code
* def _create_dynamic_model(self, model_label, fields, attributes=None,
options=None): from django.db import models class
Meta: pass setattr(Meta, 'app_label', '_talos') if
options is not None: for key, value in
options.items(): setattr(Meta, key, value) attrs =
{'__module__': '_talos', '_talos_dynamic': True, 'Meta': Meta} if
attributes: attrs.update(attributes) if
fields: attrs.update(fields) model = type(model_label,
(models.Model,), attrs) return model*
I call it like this (where self.model is referenced model class)
def _create_object_permission_model(self):
from django.db import models
return self._create_dynamic_model(
'o_{0}_{1}'.format(self.model._meta.app_config.label,
self.model.__name__),
fields={
'role': models.ForeignKey(
'talos.Role',
related_name='+',
on_delete=models.CASCADE),
'permission': models.ForeignKey(
'talos.ObjectPermission',
related_name='+',
on_delete=models.CASCADE),
'target': models.ForeignKey(
self.model,
related_name='talos_permissions', # self.model does not
receive reverse relation!
on_delete=models.CASCADE)
},
options={
'unique_together': [('role', 'permission', 'target')],
'index_together': [
('target', 'permission', 'role'),
('target', 'role', 'permission'),
('role', 'target', 'permission')]
})
I tried calling contribute_to_class and contribute_to_related_class methods
manually, tried to call this code at different moments (My application
ready method, class_prepared signal handler), with absolutely no luck.
I tried to read Django sources, and got that contribute_to_related_class is
called from contribute_to_class with delay, but it did not help me realize
what exactly I am doing wrong.
I am trying to use reverse relation from custom view and admin, so
everything should be pretty much initialized already.
Roman
My problem is very rare so I'll try ad add as much useful detail as
possible.
I am using python 3.5 and 3.6, Django 1.11.4
I am creating complex security related application and need to generate
additional models based on other applications' models. In general,
everything works fine, models are created, migrated without a problem. But
there is single problem I totally failed to solve.
Let's say there is preexisting model Alpha of some other application and I
dynamically create model Beta which references Alpha with ForeignKey. The
problem is that Beta does not get reverse relation, so I can query for
beta.alpha, but not for alpha.betas. I receive
"django.core.exceptions.FieldError: Cannot resolve keyword 'betas' into
field. Choices are: x, y, z"
Here is my code
* def _create_dynamic_model(self, model_label, fields, attributes=None,
options=None): from django.db import models class
Meta: pass setattr(Meta, 'app_label', '_talos') if
options is not None: for key, value in
options.items(): setattr(Meta, key, value) attrs =
{'__module__': '_talos', '_talos_dynamic': True, 'Meta': Meta} if
attributes: attrs.update(attributes) if
fields: attrs.update(fields) model = type(model_label,
(models.Model,), attrs) return model*
I call it like this (where self.model is referenced model class)
def _create_object_permission_model(self):
from django.db import models
return self._create_dynamic_model(
'o_{0}_{1}'.format(self.model._meta.app_config.label,
self.model.__name__),
fields={
'role': models.ForeignKey(
'talos.Role',
related_name='+',
on_delete=models.CASCADE),
'permission': models.ForeignKey(
'talos.ObjectPermission',
related_name='+',
on_delete=models.CASCADE),
'target': models.ForeignKey(
self.model,
related_name='talos_permissions', # self.model does not
receive reverse relation!
on_delete=models.CASCADE)
},
options={
'unique_together': [('role', 'permission', 'target')],
'index_together': [
('target', 'permission', 'role'),
('target', 'role', 'permission'),
('role', 'target', 'permission')]
})
I tried calling contribute_to_class and contribute_to_related_class methods
manually, tried to call this code at different moments (My application
ready method, class_prepared signal handler), with absolutely no luck.
I tried to read Django sources, and got that contribute_to_related_class is
called from contribute_to_class with delay, but it did not help me realize
what exactly I am doing wrong.
I am trying to use reverse relation from custom view and admin, so
everything should be pretty much initialized already.
Roman
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/762bd583-1daa-4229-8355-21c9fc821986%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/762bd583-1daa-4229-8355-21c9fc821986%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.