Opened 6 years ago
Last modified 6 years ago
#30002 closed Uncategorized
Dynamic model — at Initial Version
Reported by: | Artem | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 2.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I have ProjectCategoryCountPartition model
class ProjectCategoryCountPartition(models.Model): city_slug = models.CharField(verbose_name=_('City slug'), max_length=255, db_index=True) domain = models.CharField(verbose_name=_('Site name'), max_length=255) category_id = models.PositiveIntegerField(verbose_name=_('Category id')) name = models.CharField(verbose_name=_('Category project name'), max_length=255) count = models.PositiveIntegerField(default=0) class Meta: db_table = "wbtm_projects_category_partition" class DefaultMeta: db_table = "wbtm_projects_category_partition" ATTRIBUTE = { 'city_slug': models.CharField(verbose_name=_('City slug'), max_length=255, db_index=True), 'domain': models.CharField(verbose_name=_('Site name'), max_length=255), 'category_id': models.PositiveIntegerField(verbose_name=_('Category id')), 'name': models.CharField(verbose_name=_('Category project name'), max_length=255), 'count': models.PositiveIntegerField(default=0) } @classmethod def check_partition(cls, city_slug): city_slug = cls.check_city_slug(city_slug) default_db_table = cls.DefaultMeta.db_table new_db_table = "{}_{}".format(default_db_table, city_slug) if new_db_table in connection.introspection.table_names(): return True return False @classmethod def check_city_slug(cls, city_slug): city_slug = city_slug.replace('-', '_') if not re.match('^[a-zA-Z0-9_]+?$', city_slug): raise Exception('Unsupported city_slug') return city_slug @classmethod def create_partition(cls, city_slug): city_slug = cls.check_city_slug(city_slug) default_db_table = cls.DefaultMeta.db_table new_db_table = "{}_{}".format(default_db_table, city_slug) if cls.check_partition(city_slug): return new_db_table queries = [ """ CREATE TABLE {}() INHERITS ({}); """.format(new_db_table, default_db_table), ] cursor = connection.cursor() for query in queries: cursor.execute(query) return new_db_table @classmethod def get_city_model(cls, city_slug): city_slug = cls.check_city_slug(city_slug) model_name = city_slug.replace('_','') db_table = cls.create_partition(city_slug) attrs = cls.DefaultMeta.ATTRIBUTE.copy() attrs.update({ '__module__': ProjectCategoryCountPartition.__module__, 'Meta': type( 'Meta', (), dict( # managed=False, db_table=db_table, ) ), }) return type("ProjectCategoryCountPartition{}".format(model_name), (models.Model,), attrs)
I write method:
for city in ['moskva', 'london']: ProjectCategoryCountPartitionModel = ProjectCategoryCountPartition.get_city_model(project_city.slug) print(ProjectCategoryCountPartitionModel.objects.filter( city_slug=city, domain='site.ru', category_id=1, ).query) data = {'name': 'Cat1', 'count': 1} ProjectCategoryCountPartitionModel.objects.update_or_create( city_slug=city, domain='site.ru', category_id=1, defaults=data )
But, Second call ProjectCategoryCountPartitionModel, return error query. Example:
SELECT "wbtm_projects_category_partition_london"."id", "wbtm_projects_category_partition_moskva"."city_slug", "wbtm_projects_category_partition_moskva"."domain", "wbtm_projects_category_partition_moskva"."category_id", "wbtm_projects_category_partition_moskva"."name", "wbtm_projects_category_partition_moskva"."count" FROM "wbtm_projects_category_partition_london" WHERE ("wbtm_projects_category_partition_moskva"."category_id" = 1 AND "wbtm_projects_category_partition_moskva"."city_slug" = 'london' AND "wbtm_projects_category_partition_moskva"."domain" = 'site.ru')
Why are the previous model fields cached in the new model?
Note:
See TracTickets
for help on using tickets.