2009-06-09 91 views
1

我正在写一个基于Django的简单CMS。大多数内容管理系统依靠在固定URL上使用具有一个或多个可编辑区域的模板的固定页面。要拥有可编辑的区域,您需要一个页面。要让系统计算出哪个页面,您需要URL。如何从另一个Django模型中非法链接任何对象/模型?

问题出现在你不再处理“页面”(是那些FlatPages页面或其他)时,而是来自另一个模型的实例。例如,如果我有一个产品模型,我可能希望创建一个内部具有多个可编辑区域的详细信息页面。

可能建立这些区域到模型中,但在我的情况下,有几个模型,并在我想显示多少数据有很大的方差。

因此,我想要在模板级构建CMS,并指定块(可编辑区域)基于“页面”实例或其使用的模型的内容。

我有这个想法,也许我可以放弃网页这样的自定义模板标签:

{% block unique_object "unique placeholder name" %} 

这将查找基于两个参数中的一个例子通过了“块”:

<h1>{{ product_instance.name }}</h1> 
{% block product_instance "detail: product short description" %} 
{% block product_instance "detail: product video" %} 
{% block product_instance "detail: product long description" %} 

听起来很漂亮吧?那么我遇到的问题是如何为区域创建一个“键”,以便我可以将正确的区块拉出来?我将处理一个完全未知的对象(它可能是一个“页面”对象,一个URL,一个模型实例,任何东西 - 它甚至可能是一艘船</fg>)。

其他Django微应用程序必须这样做。你可以用django-tagging标记任何东西,对吧?我试图理解这是如何工作,但我画空白。

所以,首先,我疯了吗?假设我没有,并且这看起来像一个相对理智的想法,我应该如何将一个对象+字符串链接到块/可编辑区域?

注意:编辑将完成页面因此,让用户编辑区域没有真正的问题。我不需要在管理员中做任何反向巨型超大型游戏。我最终的梦想是允许第三个参数指定这是什么类型的内容区域(文本,图像,视频等)。如果您对此有任何意见,我很乐意阅读它们!

+0

打开赏金。我需要一个如何使用contenttypes对模型进行编码的示例,以及一个示例,向我展示如何使templatetag获取对象实例和字符串以定位模型。 – Oli 2009-07-29 14:15:12

+0

我无法理解您的问题域。你能澄清一下:你正在使用的模型是什么,他们期望的关系是什么? – John 2009-08-02 04:46:25

+0

这个问题的唯一核心是我的Block模型。但我需要能够使用字符串和通用对象实例混合来识别“Block”实例。例如,我可以将“Block”实例链接到CMS“Page”实例以及一个标题为“title”或“Product”实例和“title”,“footer”等的字符串。 – Oli 2009-08-02 14:59:43

回答

6

django-tagging使用Django的contenttypes框架。文档比我能解释得好得多,但最简单的描述是“可指向任何其他模型的通用外键”。

这可能是你在找什么,但是从你的描述它听起来也像是你想要做的非常相似,其他一些现有项目的东西:

  • django-flatblocks(” ...行为像django.contrib.flatpages但对于一个页面的部分。就像一个编辑框帮你想一同显示的主要内容“)

  • django-better-chunks(”把它看成是对的flatpages可重用内容哟小位你可能想插入你的模板并从管理界面进行管理。“)

等等。如果这些是相似的然后他们会成为一个很好的起点为您服务。

2

你想要的方式显示在一个通用模板的一些具体对象的内容,给出一个特定的对象,正确吗?

为了支持模型和其他对象,我们需要两个中间模型:一个用于处理字符串,一个用于处理模型,我们可以用一个模型来完成,但这不是高性能。这些模型将提供内容和字符串/模型之间的链接

from django.db import models 
from django.contrib.contenttypes.models import ContentType 
from django.contrib.contenttypes import generic 

CONTENT_TYPE_CHOICES = (
    ("video", "Video"), 
    ("text", "Text"), 
    ("image", "Image"), 
) 

def _get_template(name, type): 
    "Returns a list of templates to load given a name and a type" 
    return ["%s_%s.html" % (type, name), "%s.html" % name, "%s.html" % type] 

class ModelContentLink(models.Model): 
    key = models.CharField(max_length=255) # Or whatever you find appropriate 
    type = models.CharField(max_length=31, choices= CONTENT_TYPE_CHOICES) 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    object = generic.GenericForeignKey('content_type', 'object_id') 

    def get_template(self): 
     model_name = self.object.__class__.__name__.lower() 
     return _get_template(model_name, self.type) 

class StringContentLink(models.Model): 
    key = models.CharField(max_length=255) # Or whatever length you find appropriate 
    type = models.CharField(max_length=31, choices= CONTENT_TYPE_CHOICES) 
    content = models.TextField() 

    def get_template(self): 
     return _get_template(self.content, self.type) 

现在,我们需要的是一个模板标签来抓取这些,然后尝试加载由模型的get_template()方法给出的模板。我有点紧张,所以我会留在这里,并在1小时内更新它。如果您认为这种方法看起来不错,请告诉我。

2

这是非常简单的使用contenttypes框架实现的查找策略你所描述的:

class Block(models.Model): 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    object = generic.GenericForeignKey() # not actually used here, but may be handy 
    key = models.CharField(max_length=255) 
    ... other fields ... 

    class Meta: 
     unique_together = ('content_type', 'object_id', 'key') 

def lookup_block(object, key): 
    return Block.objects.get(content_type=ContentType.objects.get_for_model(object), 
          object_id=object.pk, 
          key=key) 

@register.simple_tag 
def block(object, key) 
    block = lookup_block(object, key) 
    ... generate template content using 'block' ... 

有一个问题需要注意的是,你不能在Block.objects.get呼叫使用object领域,由于这不是一个真正的数据库领域。您必须使用content_typeobject_id

我叫模式Block,但如果你有一些情况下,多个唯一(object, key)元组映射到相同的块,它实际上可能是本身具有ForeignKey您的实际Block模型或到中间模型在Van Gale提到的助手应用程序中使用适当的模型。

相关问题