2009-06-09 3 views
1

저는 장고를 기반으로 한 간단한 CMS를 작성하고 있습니다. 대부분의 콘텐츠 관리 시스템은 하나 이상의 수정 가능 영역이있는 템플릿을 사용하여 고정 된 URL에 고정 페이지를 사용합니다. 편집 가능한 영역을 가지려면 페이지가 필요합니다. 시스템에서 어떤 페이지를 작동 시키려면 URL이 필요합니다.객체/모델을 다른 Django 모델과 연결시키는 방법은 무엇입니까?

문제는 더 이상 "페이지"(플랫 페이지 페이지 등)가 아니라 다른 모델의 인스턴스를 처리 할 때 발생합니다. 예를 들어 제품 모델이있는 경우 편집 가능한 여러 영역이있는 세부 정보 페이지를 만들 수 있습니다.

은 모델에 해당 지역을 구축 할 수 있지만 제 경우에는 여러 모델이 있으며 표시하려는 데이터의 양이 많은 편입니다.

따라서 템플릿 수준에서 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 마이크로 애플리케이션이이를 수행해야합니다. 장고 태그 붙이기로 무엇이든 태그 할 수 있습니다. 어떻게 작동하는지 이해하려고 노력했지만 공백을 그리는 중입니다.

그래서, 첫째로, 나는 화가 났습니까? 그리고 그렇지 않다고 가정하면, 이것은 상대적으로 정상적인 아이디어로 보입니다. 객체 + 문자열을 블록/편집 가능 영역에 연결하려면 어떻게해야합니까?

참고 : 편집은 페이지에서 이루어 지므로 사용자가 영역을 편집하도록 허용하지 않습니다. 나는 관리자에게 어떤 불쾌한 점보도하지 않아도됩니다. 내 궁극적 인 꿈은 세 번째 인수가 콘텐츠 영역의 종류 (텍스트, 이미지, 비디오 등)를 지정하도록 허용하는 것입니다. 이것에 대한 의견이 있으시면 언제든지 읽을 수 있습니다!

+0

현상금을 여는 중입니다. contenttypes를 사용하여 모델을 코딩하는 방법과 템플릿 인스턴스를 객체 인스턴스로 만들고 모델을 찾기 위해 문자열을 만드는 방법을 보여주는 예제가 필요합니다. – Oli

+0

문제 도메인을 이해하는 데 문제가 있습니다. 당신은 분명히 할 수 있습니다 : 당신이 작업하고있는 모델은 무엇이며, 그들이 원하는 관계는 무엇입니까? – John

+0

유일한 모델 핵심은 제 '블록'모델입니다. 하지만 문자열과 일반 객체 인스턴스를 혼합하여 'Block'인스턴스를 식별 할 수 있어야합니다. 예를 들어,'Block' 인스턴스를 CMS의'Page' 인스턴스와 "title"또는'Product' 인스턴스와 "title", "footer"등의 문자열로 연결할 수 있습니다. – Oli

답변

6

장고 태그 지정은 장고의 contenttypes 프레임 워크를 사용합니다. 문서는 내가 할 수있는 것보다 훨씬 더 잘 설명 할 수 있지만 가장 간단한 설명은 "다른 모든 모델을 가리킬 수있는 일반적인 외래 키"입니다.

당신이 다른 기존 프로젝트와 매우 비슷한 싶지처럼이 당신이 찾고있는, 그러나 당신의 설명에서도 소리가 무엇을 할 수

  • django-flatblocks ("... 행위를 "

  • django-better-chunks()는"다시 사용할 수있는 콘텐츠 요의 작은 비트의 flatpages이라고 생각하면 메인 컨텐츠 옆에 표시하려면 편집 가능한 도움말 상자처럼, django.contrib.flatpages처럼하지만 페이지의 부품. 템플릿에 삽입하고 관리 인터페이스에서 관리 할 수 ​​있습니다.")

이러한 비슷한 경우 등등. 그들은 당신을위한 좋은 출발점을 만들 수 있습니다.

+0

정확히 예를 들어 설명하겠다.) – Jiaaro

+0

이러한 예제는 거의 비슷하지만 내 요구 사항 중 가장 중요한 부분 인 객체에 바인딩되어 있지 않습니다. 질문에 현상금을 열었습니다. 당신이 충분히 정교 할 수 있다면, 그 점들이 당신 것입니다. – Oli

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 시간 안에 그것을 업데이트 할 것이다. 이 접근법이 좋다고 생각되면 알려주세요. 때문에, 당신은 Block.objects.get 호출에서 object 필드를 사용할 수 있다는 것입니다 알고 있어야

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' ... 

하나 잡았다을 :

+0

CONTENT_TYPE_CHOICES에 대한 이야기가 재미 있습니다. 나는 그것이 두 가지 서류를 남겨 두었습니다. 왜냐하면 과도하게 복잡하다고 생각 했으니까요.하지만 당신이 같은 페이지에 있다는 것을 보는 것이 좋습니다. 하지만 ... 계속 ... – Oli

+0

여기에서 중요한 문제는 (틀렸다면 나에게 맞춰주세요) 이것은 단지 컨텐트에 연결됩니다 * 일반 모델 *** 또는 ***에서 문자열로 연결됩니다. 콘텐츠 블록을위한 키가 둘 다 다양한 조합이되어야합니다. IE에서는 블록 (예 : 제품의 객체 인스턴스)을 특정 지정하고 그 페이지 스타일 (예 : "title"을 나타내는 문자열)에 특정한 것을 지정하기 때문에 시스템은 블록을로드하는 것을 알고 있습니다. 이 조합은 해당 제품과 "제목"이 요구되는 상황에 고유 한 콘텐츠 블록을 제공합니다. – Oli

+0

아니면 내가 근시안적입니까? 나는이 클래스가 필요하다는 것을 알기 때문에 약간 생각하지만, 가상의 templatetag가있는 페이지에서는 어떻게 작동 할까? 하나의 문자열과 하나의 객체를 사용한다고 가정하면, 두 개의 조회 결과 (ModelContentLink와 StringContentLink)를 교차 비교해야합니다. 그것을하는 빠른 (읽기 : 효율적인) 방법이 있을지 모르지만 나는 그것을 모른다 ... – Oli

2

그것은 당신이 설명하는 조회 전략을 구현하기 위해 contenttypes 프레임 워크를 사용하는 매우 간단합니다 그것은 실제 데이터베이스 필드가 아닙니다. content_typeobject_id을 사용해야합니다.

나는 모델 Block라고,하지만 당신은 어떤 경우가 있다면 어디 동일한 블록에 두 개 이상의 독특한 (object, key) 튜플지도, 그것은 사실 자체가 실제 Block 모델에 나에 ForeignKey이있는 중간 모델이 될 수 있습니다 Van Gale이 언급 한 것과 같은 도우미 앱의 적절한 모델입니다.

관련 문제