如何在Django中创建多对一关系并在管理界面显示
我遇到了一个问题——我想在Django中创建一种多对一的关系,用来表示对象和对象的部分之间的关系,比如:
class Website(models.Model):
name = models.CharField(max_length = 100)
class WebsiteIp(models.Model):
website = models.ForeignKey(Website, primary_key = True)
ip = models.CharField(max_length = 40, primary_key = True)
introduction_date = models.DateField()
这些关系都应该在网站上(父对象)的编辑页面上展示。虽然听起来这个问题很简单,但我真的找不到什么有用的资料来解决这个问题。
2 个回答
0
解决这个问题的方法是修改依赖关系的主键设置(但这种方法只适用于像这种情况——当有一个可能在整个表中唯一的键时,比如这里的ip)。
class WebsiteIp(models.Model):
website = models.ForeignKey(Website)
ip = models.CharField(max_length = 40, primary_key = True)
introduction_date = models.DateField()
在做完这个步骤之后(而且只有在这个步骤之后),mkoistinen 提出的部分解决方案才会按预期工作。一般来说,问题在于django在检查能否创建新对象时,错误地检查了主键列的唯一性。因此,我猜也可以通过重写一些models.Model的方法来修复这个问题,但我对django的内部机制了解不够,无法指出具体是哪个方法。
3
在你的WebsiteIP的ForeignKey中添加related_name参数,像这样:
class Website(models.Model):
name = models.CharField(max_length = 100)
class WebsiteIp(models.Model):
website = models.ForeignKey(Website, primary_key = True, related_name="IPs")
ip = models.CharField(max_length = 40)
introduction_date = models.DateField()
然后,你可以像这样从Website引用多个IP,形成一个多对一的关系:
website = Website.objects.filter(name="blah")
if website.count():
IPs = website[0].IPs
当然这只是个初步的想法,具体还需要测试,但这应该能帮你找到正确的方向。另外,你可以查看这个链接了解更多:https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-one-relationships
在你的admin.py文件中,假设你有类似这样的代码:
class WebsiteAdmin(admin.ModelAdmin):
list_display = ('name',)
search_fields = ['name']
ordering = ('name', )
更新为以下内容:
class WebsiteIpInline(admin.TabularInline):
model = WebsiteIp
extra = 1
class WebsiteAdmin(admin.ModelAdmin):
list_display = ('name',)
search_fields = ['name']
inlines = ( WebsiteIpInline, )
ordering = ('name', )
这样应该能显示你想要的结果!