2009-06-09 11 views
1

私はDjangoベースのシンプルなCMSを書いています。ほとんどのコンテンツ管理システムは、1つまたは複数の編集可能な領域を持つテンプレートを使用して、固定URLに固定ページを置くことに依存しています。編集可能な領域を作成するには、ページが必要です。システムがどのページを処理するためには、URLが必要です。 オブジェクト/モデルを別のDjangoモデルから無関係にリンクするには?

「ページ」(フラットページページなど)ではなく、別のモデルからのインスタンスを扱うことがなくなったときに問題が発生します。たとえば、製品のモデルがある場合、複数の編集可能な領域がある詳細ページを作成することができます。

私の場合、いくつかのモデルがあり、表示したいデータの量にばらつきがあります。

したがって、テンプレートレベルでCMSを構築し、「ページ」のインスタンスまたは使用するモデルに基づいてブロック(編集可能領域)を指定する必要があります。

{% block unique_object "unique placeholder name" %} 

そして、それは一例に渡された2つの引数に基づいて「ブロック」を見つけるだろう:。

は、私は多分、私がこのようなページにカスタムテンプレートタグをダンプすることができないという考えを持っていました:

<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タグで何かをタグ付けすることができます。私はその仕組みを理解しようとしましたが、私は空白を描いています。

まず、私は怒っていますか?そして私がそうではないと仮定すると、これは比較的賢明なアイデアのように見えますが、オブジェクト+文字列をブロック/編集可能領域にリンクするにはどうすればよいですか?

注:編集はオンザページで行われるため、ユーザーがゾーンを編集できるようにするための実際の問題はありません。私は管理者の中で逆のジャンボをする必要はありません。私の最終的な夢は、これがどのような種類のコンテンツ領域(テキスト、イメージ、ビデオなど)を指定するために3番目の引数を許可することです。これに関するコメントがあれば、私はそれらを読むことができます!

+0

賞金を稼ぐ。私はcontenttypesを使ってモデルをコーディングする方法の例と、templatetagをオブジェクトインスタンスにする方法と、モデルを見つけるための文字列を示す例が必要です。 – Oli

+0

問題のドメインを理解できません。あなたは、あなたが働いているモデルは何ですか?そして、彼らの希望する関係は何ですか? – John

+0

問題の唯一のモデルコアは私の 'ブロック'モデルです。しかし、私は文字列と汎用オブジェクトのインスタンスを組み合わせて 'Block'インスタンスを識別できる必要があります。たとえば、 'Block'インスタンスをCMSの' Page'インスタンスに、 'title'や' Product'インスタンス、 'title'、' footer "などとリンクすることができます。 – Oli

答えて

6

djangoのタグ付けでは、Djangoのcontenttypesフレームワークが使用されます。ドキュメントは私よりもはるかに優れた説明をしてくれますが、最も簡単な説明は「他のモデルを指すことができる汎用の外部キー」です。

これは、あなたが探しているものかもしれないが、あなたには、いくつかの他の既存のプロジェクトに非常によく似た何かをしたいようにあなたの説明からも聞こえる:

  • django-flatblocks(」...行為「

  • django-better-chunks()は、」再利用可能なコンテンツヨーヨーの小さなビットのためにflatpagesとして考えてあなたがメインのコンテンツと一緒に表示したい編集可能なヘルプボックスのように、django.contrib.flatpagesようですが、ページの一部のために。あなたのテンプレートに挿入し、管理インターフェースから管理したいかもしれません。ように「)

と。これらが類似している場合、彼らはあなたのための良い出発点を作ってあげる。

+0

これはまさに私が例として持ってきたアプリだ); – Jiaaro

+0

これらの例は近いが、要件に最も重要な部分が欠落している。オブジェクトにバインドされている。私は質問に恩恵を受けました。あなたが十分に精巧にできるならば、ポイントはあなたのものです。 – Oli

2

あなたが与えられ、汎用テンプレート上のいくつかのオブジェクト固有のコンテンツを表示する方法をしたいです

モデルと他のオブジェクトの両方をサポートするには、文字列を扱うモデルとモデルを扱うモデルの2つの中間モデルが必要です。モデルは1つではありませんが、パフォーマンスは劣りますこれらのモデルは、コンテンツと文字列/モデルの間のリンクを提供します。

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時間後に更新します。このアプローチがきれいだと思ったら教えてください。

+0

CONTENT_TYPE_CHOICESに言及すると面白いです。私はそれを複雑すぎると思ったので両方のブリーフアウトを残していましたが、あなたが同じページにいるのを見るのは良いことです。しかし...続き... – Oli

+0

ここでの主な問題は、(私が間違っている場合は私を修正してください)これはコンテンツへのリンクです*ジェネリックモデル***または***からの文字列。コンテンツブロックのキーが両方の可変的な組み合わせである必要があります。 IEではブロックをロードすることが知られています。これは、そのページに固有のもの(製品のオブジェクトインスタンスなど)を指定し、そのページのスタイルに固有のもの(例: "title"という文字列)を指定するためです。この組み合わせは、その製品と「タイトル」の両方が求められる状況に特有のコンテンツブロックを提供します。 – Oli

+0

また、私は近視眼鏡ですか?私はこれらのクラスの必要性を見ているので少しだと思いますが、架空のtemplatetagを持つページではどのように動作しますか? 1つの文字列と1つのオブジェクトを使用すると仮定すると、2つの参照(ModelContentLinkとStringContentLinkの両方)の結果を相互比較する必要があります。それを行う高速(読み込み:効率的な)方法があるかもしれませんが、私はそれを知らない... – Oli

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)タプルマップいくつかのケースを持っている場合、それは実際に自身が実際BlockモデルかにForeignKeyを持っている中間モデルもありVan Galeが言及したようなヘルパーアプリで適切なモデルを作成します。

関連する問題