如何建立m2m关系的模型,其中相关表可以是城市,地区(州)或国家

时间:2010-08-27 02:03:54

标签: python django

在Django我有这些模型:

class Artist(models.Model):
    name = models.CharField(max_length=128)
    born_place = models.ForeignKey(???)
    dead_place = models.ForeignKey(???)
    live_places = models.ManyToManyField(???)
    work_places = models.ManyToManyField(???)

class Country(models.Model):
    iso = models.CharField(max_length=2, primary_key=True)
    name = models.CharField(max_length=50)

class Region(models.Model):
    iso = models.CharField(max_length=2, blank=True)
    name = models.CharField(max_length=150)
    country = models.ForeignKey('Country')

class City(models.Model):
    name = models.CharField(max_length=150)
    region = models.ForeignKey('Region')

所有地方born_placedead_placelive_placeswork_places)可以是City或{{ 1}}或RegionCountry必须有CityRegion必须有Region

我怎样才能实现这一目标?

4 个答案:

答案 0 :(得分:1)

  

所有地方(born_place,dead_place,live_places,work_places)可以是城市,地区或国家。

在这种情况下,您需要的是generic foreign key。在Django中,这可以通过方便的contenttypes框架来实现。

来自文档:

  

设置GenericForeignKey有三个部分:

     
      
  1. 为您的模型提供一个ForeignKey到ContentType。

  2.   
  3. 为您的模型提供一个字段,该字段可以存储您要与之相关的模型中的主键值。 (对于大多数模型,这意味着IntegerField或PositiveIntegerField。)此字段的类型必须与将在通用关系中涉及的模型的主键相同。例如,如果使用IntegerField,则无法与使用CharField作为主键的模型形成通用关系。

  4.   
  5. 为您的模型提供GenericForeignKey,并将其传递给上述两个字段的名称。如果这些字段名为“content_type”和“object_id”,则可以省略 - 这些是GenericForeignKey将查找的默认字段名称。

  6.   

答案 1 :(得分:1)

好吧..也许你可以使用通用关系。但我认为你可以通过跳出框框思考来解决一些问题。

我会说你可以创建一个Territory模型而不是Country,Region和City;然后使用recursive relationship

class Territory(models.Model):
   iso = models.CharField(max_length=2, blank=True)
   name = models.CharField(max_length=150)
   parent = models.ForeignKey('self')

这将为您的区域创建一个层次结构,所以现在您可以使用任意数量的分区(例如,大陆,行星,社区),您不必更改模型。至于艺术家,你可以这样做:

class Artist(models.Model):
    name = models.CharField(max_length=128)
    born_place = models.ForeignKey(Territory)
    dead_place = models.ForeignKey(Territory)
    live_places = models.ManyToManyField(Territory)
    work_places = models.ManyToManyField(Territory)

所以现在...... born_place可以是一个城市,一个地区,一个星球......你想要的任何东西!我猜这是你的问题。我不是django的专家,这只是解决O.O.P中这类问题的通用方法。

答案 2 :(得分:1)

您也可以使用模型继承

class Territory(models.Model):
    name = models.CharField(max_length=150)

class Country(Territory):
    iso = models.CharField(max_length=2, primary_key=True)

class Region(Territory):
    iso = models.CharField(max_length=2, blank=True)
    country = models.ForeignKey('Country')

class City(Territory):
    region = models.ForeignKey('Region')

class Artist(models.Model):
    name = models.CharField(max_length=128)
    born_place = models.ForeignKey(Territory)
    dead_place = models.ForeignKey(Territory)
    live_places = models.ManyToManyField(Territory)
    work_places = models.ManyToManyField(Territory)

祝你好运!

答案 3 :(得分:0)

查看Django的通用关系herehere,它们可以让您键入各种类型的对象,而不仅仅是特定的对象。