关于python:创建一个新模型,其中包含当前现有模型的所有字段

Create a new model which have all fields of currently existing model

我正在用我的django应用程序制作一个模型Player

1
2
3
4
5
6
7
class Player(models.Model):
   """ player model"""
    name = models.CharField(max_length=100, null=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True)
    last_updated = models.DateTimeField(auto_now=True)
    hash = models.CharField(max_length=128, null=True, blank=True)
    bookmark_url = models.CharField(max_length=300, null=True, blank=True)

根据我的要求,我需要创建一个新的模型BookmarkPlayer,它将具有Player模型的所有字段。

现在我有两件事要做。

  • 我可以为bookmarkplayer模型扩展player类。
  • 1
    2
    3
    4
        class BookmarkPlayer(Player):
           """ just a bookmark player"""
            class Meta:
                app_label ="core"
  • 我可以将播放器模型的所有字段定义为bookmarkplayer模型。
  • 1
    2
    3
    4
    5
    6
    7
         class BookmarkPlayer(models.Model):
               """ bookmark player model"""
                name = models.CharField(max_length=100, null=True, blank=True)
                date_created = models.DateTimeField(auto_now_add=True)
                last_updated = models.DateTimeField(auto_now=True)
                hash = models.CharField(max_length=128, null=True, blank=True)
                bookmark_url = models.CharField(max_length=300, null=True, blank=True)

    我只想知道哪种方法更好。如果还有别的好方法,请和我分享。

    更新的问题

    Knbb创建基类的想法很有趣,但我面临的问题是我的一个模型已经存在于数据库中。

    我的实际型号:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Address(models.Model):
        address = models.TextField(null=True, blank=True)


    class Site(models.Model):
        domain = models.CharField(max_length=200)


    class Player(models.Model):
        # ... other fields
        shipping_address = models.ForeignKey(Address, related_name='shipping')
        billing_address = models.ForeignKey(Address, related_name='billing')
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now_add=True)
        site = models.ManyToManyField(Site, null=True, blank=True)

        class Meta:
           abstract = True

    更改后的模型:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class Address(models.Model):
        address = models.TextField(null=True, blank=True)


    class Site(models.Model):
        domain = models.CharField(max_length=200)


    class BasePlayer(models.Model):
        # .. other fields
        shipping_address = models.ForeignKey(Address, related_name='shipping')
        billing_address = models.ForeignKey(Address, related_name='billing')
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now_add=True)
        site = models.ManyToManyField(Site, null=True, blank=True)

        class Meta:
           abstract = True

    class Player(BasePlayer):
       class Meta:
           app_label = 'core'


    class BookmarkPlayer(BasePlayer):
        class Meta:
            app_label = 'core'

    在这些更改之后,当我运行Django服务器时,我会收到下面给出的错误。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    django.core.management.base.CommandError: One or more models did not validate:
    core.test1: Accessor for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'.
    core.test1: Reverse query name for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'.
    core.test1: Accessor for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address'.
    core.test1: Reverse query name for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address'.
    core.test2: Accessor for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'.
    core.test2: Reverse query name for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'.
    core.test2: Accessor for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address'.
    core.test2: Reverse query name for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address'

    答:最后,如果我们将foreignkey或manytomanyfield上的相关_name属性用于抽象模型,我得到了答案。这通常会在抽象基类中引起问题,因为这个类上的字段包含在每个子类中,每次属性(包括相关的名称)的值都完全相同。为了解决这个问题,在抽象基类中使用相关的_名称(仅限)时,名称的一部分应包含"%"(app_label)s'和"%"(class)s'。https://docs.djangoproject.com/en/dev/topics/db/models/抽象基类现在我的棒球手模型是

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class BasePlayer(models.Model):
        # .. other fields
        shipping_address = models.ForeignKey(Address, related_name='%(app_label)s_%(class)s_shipping')
        billing_address = models.ForeignKey(Address, related_name='%(app_label)s_%(class)s_billing')
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now_add=True)
        site = models.ManyToManyField(Site, null=True, blank=True)

        class Meta:
           abstract = True


    如果您的BookmarkPlayer需要相同的数据,但在不同的表中,抽象的基础模型是最好的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class BasePlayer(models.Model):
        name = models.CharField(max_length=100, null=True, blank=True)
        date_created = models.DateTimeField(auto_now_add=True)
        last_updated = models.DateTimeField(auto_now=True)
        hash = models.CharField(max_length=128, null=True, blank=True)
        bookmark_url = models.CharField(max_length=300, null=True, blank=True)

        class Meta:
            abstract = True

    class Player(BasePlayer):
       """ player model"""
        pass

    class BookmarkPlayer(BasePlayer):
       """ bookmark player model"""
        pass

    这样,PlayerBookmarkPlayer都从BasePlayer模型继承了它们的字段,但由于BasePlayer是抽象的,因此模型完全分离。

    另一方面,多表继承仍然可以将字段保存在一个表中,但是为BookmarkPlayer添加一个额外的表,并将隐式OneToOneField添加到Player表中。


    这里有一些关于模型继承的好信息:https://docs.djangoproject.com/en/1.7/topics/db/models/模型继承

    选项2将引入重复,这总是很糟糕的。如果BookmarkPlayer没有任何新字段,只有不同的方法,我建议您使用链接中描述的"代理模型"选项,因为您不需要BookmarkPlayer在数据库中拥有它自己的表。

    如果它需要它自己的表,"多表固有"是一种方式,这将是您的问题中的选项1。