【问题标题】:Django, autogenerate one-to-many tables, and database structureDjango,自动生成一对多表和数据库结构
【发布时间】:2012-07-22 11:05:21
【问题描述】:

我在一个网站上使用 django,我有一个包含用户、人员、位置、项目等的数据库。知道我发现我需要一些额外的信息,这些信息需要像 Aliases 这样的一对多关系来处理大多数表格。

我应该 (1) 使用内容类型框架为所有这些创建一个通用别名表(最终可能会有数十亿行),还是应该 (2) 为每个创建一个别名表。如果是后者,我如何通过像这样添加一行来自动创建这样的一对多表

"别名 = Ailias()"

在每个模型中。我敢肯定,不久前我看到一个应用程序在做类似的事情,我认为这是某种类型的回归应用程序。即使第二种方法不适合,我也希望了解如何去做。我不知道要搜索什么才能找到对此的解释。

我计划为此添加带有 Solr 的 Haystack,因此方法 2 可能会在那里增加很多额外的工作。但是我对它的喷气机没有太多经验,所以我可能错了。

PS:最终选择了方法一。

【问题讨论】:

    标签: database django one-to-many


    【解决方案1】:

    设法在方法 2 中做我想做的事,轻松生成一对多字段。不确定这是最简单的方法,还是最好的方法。如果有人有更好的方法,我很想学习它。我距离 django 专家还有很长的路要走,所以我可能会插手一些不必要的复杂的东西来做我想做的事。

    此示例创建了一种添加一对多别名关系的简单方法。

    别名管理器

    class AliasManagerDescriptor(object):
    def __init__(self, model,fkName):
        self.model = model
        self.fkName = fkName
    
    def __get__(self, instance, owner):
        if instance is None:
            return AliasManager(self.model,self.fkName)
        return AliasManager(self.model, self.fkName, instance)
    
    class AliasManager(models.Manager):
    def __init__(self, model,fkName, instance=None):
        super(AliasManager, self).__init__()
        self.model = model
        self.instance = instance
        #Name of FK linking this model to linked model
        self.fkName=fkName
    
    def get_query_set(self):
        """
        Get query set, or only get instances from this model that is linked
        to the chosen instance from the linked model if one is chosen
        """
        if self.instance is None:
            return super(AliasManager, self).get_query_set()
    
        if isinstance(self.instance._meta.pk, models.OneToOneField):
            #TODO: Checkif this part works, not checked
            filter = {self.instance._meta.pk.name+"_id":self.instance.pk}
        else:
            filter = {self.fkName: self.instance.pk}
        return super(AliasManager, self).get_query_set().filter(**filter)
    
    def create(self,**kwargs):
        """
        Create alias instances. If FK is not given then it is automatically set
        to the chosen instance from the linked model
        """
        if self.fkName not in kwargs:
            kwargs[self.fkName]=self.instance
        print kwargs
        super(AliasManager, self).create(**kwargs)
    

    别名模型

    class Alias(object):
    
    def contribute_to_class(self, cls, name):
        self.manager_name = name
        aliasModel = self.create_alias_model(cls)
        descriptor = AliasManagerDescriptor(aliasModel,cls._meta.object_name.lower())
        setattr(cls, self.manager_name, descriptor)
    
    def create_alias_model(self, model):
        """
        Creates a alias model to associate with the model provided.
        """
        attrs = {
                 #'id': models.AutoField(primary_key=True),
                 "name": models.CharField(max_length=255),
    
                 #Not sure which to use of the two next methods
                 model._meta.object_name.lower(): models.ForeignKey(model),
                 #model._meta.object_name.lower(): AliasObjectDescriptor(model),
    
                 '__unicode__': lambda self: u'%s' % self.name,
                 '__module__': model.__module__
                 }
        attrs.update(Meta=type('Meta', (), self.get_meta_options(model)))
        name = '%s_alias' % model._meta.object_name
        return type(name, (models.Model,), attrs)
    
    def get_meta_options(self, model):
        """
        Returns a dictionary of fields that will be added to
        the Meta inner class.
        """
        return {
        }
    
    
    """class AliasObjectDescriptor(object):
    def __init__(self, model):
        self.model = model
    
    def __get__(self, instance, owner):
        values = (getattr(instance, f.attname) for f in self.model._meta.fields)
        return self.model(*values)"""
    

    Person Model - 只需在模型中添加“alias = Alias()”即可添加一对多别名字段。

    class Person(models.Model):
    name = models.CharField(max_length=30,blank=True,null=True)
    age = models.IntegerField(blank=True,null=True)
    
    alias = Alias()
    

    现在我可以这样做了:

    per = Person(name="Per",age=99)
    per.save()
    per.alias.create(name="Mr.P")
    per_alias = per.alias.all().values_list("name",flat=True)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多