0

ユーザー、人、場所、アイテムなどのデータベースがあるWebサイトにdjangoを使用しています。これらのテーブルのほとんどで、エイリアスのような 1 対多の関係を必要とする追加情報が必要であることがわかりました。

(1) コンテンツ タイプ フレームワークを使用して、これらすべてに共通のエイリアス テーブルを作成する必要があります (最終的に数十億行になる可能性があります)、または (2) これらのそれぞれにエイリアス テーブルを作成する必要があります。後者の場合、このような1行を追加するだけで、このような1対多のテーブルを自動作成するにはどうすればよいですか

「エイリアス=アイリアス()」

各モデルで。少し前にそのようなことをしているアプリを見たと思いますが、それはある種の復帰アプリだったと思います。2 番目の方法が適切でない場合でも、その方法を理解したいと思います。これについての説明を見つけるために何を検索すればよいかわかりません。

これに Solr を使用した Haystack を追加する予定なので、方法 2 ではさらに多くの作業が追加される可能性があります。しかし、私はそれを使った経験があまりないので、間違っているかもしれません.

PS:方法1で終わりました。

4

1 に答える 1

0

方法2でやりたかったことをなんとか実行でき、1対多のフィールドを簡単に生成できます。これが最も簡単な方法なのか、それとも最良の方法なのかわからない。誰かがそれを行うためのより良い方法を持っているなら、私はそれを学びたいです。私はdjangoの専門家から遠く離れているので、やりたいことをするために不必要な複雑なことをいじっていたかもしれません。

この例では、1対多のエイリアス関係を追加する簡単な方法を作成します。

エイリアスマネージャー

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)"""

個人モデル-1対多のエイリアスフィールドを追加するには、モデルに「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)
于 2012-07-23T13:38:05.837 に答える