我有一个非常简单的应用程序,目前宣布两个模型:一个被称为"内容"并简单地保存内容数据,另一个是" Page"其中包括"内容"作为OneToOneField。
我之所以做到这一点,是因为我可以拥有" Page"作为我使用的实际具体类,当我计划的其他模块中的其他模型需要页面数据时,它们可以简单地包括"内容"作为OneToOneField。我已经这样做了,以避免继承和使用组合。
models.py:
from django.db import models
class Content(models.Model):
"""Basic page data which can be used by other modules"""
title = models.CharField(max_length=200)
html_title = models.CharField(max_length=200)
meta_desc = models.CharField(max_length=200)
keywords = models.CharField(max_length=200)
content = models.TextField()
class Page(models.Model):
"""Concrete implementation of a basic page managed by the admin"""
slug = models.SlugField()
content = models.OneToOneField(Content)
def __str__(self):
return self.content.title
admin.py:
from django.contrib import admin
from content.models import Page, Content
class ContentInline(admin.TabularInline):
model = Content
fields = ('title', 'html_title', 'meta_desc', 'keywords', 'content')
class PageAdmin(admin.ModelAdmin):
fields = ('slug',)
inlines = [ContentInline]
在页面管理员上我得到了这个例外:
Exception at /admin/content/page/add/
<class 'content.models.Content'> has no ForeignKey to <class 'content.models.Page'>
说什么当然是正确的,但我似乎无法找到一种方法来做我想要的,包括内联关系的非定义方。我不想在&#34; Content&#34;上宣布这种关系。因为那时我必须在该类中定义它的每一个关系,这会将依赖关系引入其他模块,在我看来它应该一无所知。
在Python 3.3上使用Django 1.6。
编辑如评论中所示,我决定使用继承。我最初担心的是,我希望能够灵活地从多个其他类组成类。但是,由于Django ORM确实支持多重继承,并且如果我意识到该方法被称为&#34; mixins&#34; (Python新手)我会早点到达某个地方。
示例mixins与模型:
from django.db import models
class Content(models.Model):
"""Basic page data which can be used by other modules"""
title = models.CharField(max_length=200)
html_title = models.CharField(max_length=200)
meta_desc = models.CharField(max_length=200)
keywords = models.CharField(max_length=200)
content = models.TextField()
def __str__(self):
return self.title
class Meta:
abstract = True
class Data(models.Model):
data_name = models.CharField(max_length=200)
class Meta:
abstract = True
class Page(Content, Data):
"""Concrete implementation of a basic page managed by the admin"""
slug = models.SlugField()
然后我可以在admin.py中将其用作一个模型。
答案 0 :(得分:0)
另一种解决方案是将OneToOneField
从Content
移至Page
class Content(models.Model):
"""Basic page data which can be used by other modules"""
title = models.CharField(max_length=200)
html_title = models.CharField(max_length=200)
meta_desc = models.CharField(max_length=200)
keywords = models.CharField(max_length=200)
content = models.TextField()
page = models.OneToOneField(Page, primary_key=True, related_name="content")
class Page(models.Model):
"""Concrete implementation of a basic page managed by the admin"""
slug = models.SlugField()
def __str__(self):
return self.content.title
您仍然可以执行page.content
,内联表单将开箱即用
编辑:
该方法的一个缺点是它允许用户创建页面而不向其分配任何内容(在这种情况下page.content
将崩溃)
通过创建自定义表单
很容易克服这个问题class ContentAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
kwargs["empty_permitted"] = False
super(ContentAdminForm, self).__init__(*args, **kwargs)
然后在管理页面
class ContentInline(admin.TabularInline):
model = Content
form = ContentAdminForm
fields = ('title', 'html_title', 'meta_desc', 'keywords', 'content')
答案 1 :(得分:-1)
如果您根本不想更改模型,可以使用django模块显示非定义边内联:django_reverse_admin
您需要将django_reverse_admin添加到您的requirements.txt:
-e git+https://github.com/anziem/django_reverse_admin.git#egg=django_reverse_admin
然后导入它:
admin.py
from django.contrib import admin
from django_reverse_admin import ReverseModelAdmin
from content.models import Page, Content
# don't need to define an inline anymore for Content
class PageAdmin(ReverseModelAdmin):
fields = ('slug',)
inline_reverse = ['content']
inline_type = 'tabular' # or could be 'stacked'