Django 컨텐츠 유형은 정확히 어떻게 작동합니까?


148

Django의 콘텐츠 유형 개념을 파악하는 데 어려움을 겪고 있습니다. 그것은 매우 해킹 감을 느끼고 궁극적으로 파이썬이 일을하는 방식에 반합니다. Django를 사용하려면 프레임 워크의 범위 내에서 작업해야합니다.

그래서 나는 누군가가 컨텐츠 유형의 작동 방식과 구현 방법에 대한 실제적인 예를 제시 할 수 있는지 궁금합니다. 필자가 검토 한 거의 모든 자습서 (주로 블로그)는 실제로 개념을 다루는 데 큰 도움이되지 않습니다. 그들은 Django 문서가 사라진 곳에서 픽업하는 것처럼 보입니다 (어딘가처럼 보입니다).


5
나는 콘텐츠 유형이 다형성과 같은 것이라고 생각합니다 (누군가 나를 잘못 고치면). 프로젝트가 다양한 형태를 가질 수있는 모델을 갖기 시작하면 손에 도구가 될 것입니다. 설명서의 태그 예제는 매우 간단하지만 항목에 태그를 지정할 수는 있지만 모든 태그가 지원할 수있는 항목, 게시물, 페이지, 사용자, 제품. 컨텐츠 유형을 사용하면 관련 모델이 정확히 무엇인지 알 필요없이 다양한 구현에 대한 관계를 작성할 수 있습니다.
petkostas

1
알았어, 내가 넘어진 곳은 그들이 "TaggedItem"이라는 이름의 클래스를 만들었다는 것이다. TaggedItem이 자리 표시 자 "브릿지"클래스인지 확실하지 않았습니다. 내 자연 성향은 "term"이라는 속성을 가진 "Tag"와 같은 것일 수 있습니다.
Chris Shelton

답변:


307

작업에 컨텐츠 유형 프레임 워크를 사용 하시겠습니까?

"이 모델들 중 어떤 모델이 다른 모델과 같은 방식으로 관련되어야합니까? 우리가이 질문을하는 이유는 이것이 콘텐츠 유형 프레임 워크가 가장 잘하는 것이기 때문입니다. 모델간에 일반적인 관계를 만듭니다. Blah blah, 몇 가지 코드를 살펴보고 무슨 뜻인지 봅시다.

# ourapp.models
from django.conf import settings
from django.db import models

# Assign the User model in case it has been "swapped"
User = settings.AUTH_USER_MODEL

# Create your models here
class Post(models.Model):
  author = models.ForeignKey(User)
  title = models.CharField(max_length=75)
  slug = models.SlugField(unique=True)
  body = models.TextField(blank=True)

class Picture(models.Model):
  author = models.ForeignKey(User)
  image = models.ImageField()
  caption = models.TextField(blank=True)

class Comment(models.Model):
  author = models.ForeignKey(User)
  body = models.TextField(blank=True)
  post = models.ForeignKey(Post)
  picture = models.ForeignKey(Picture)

자, 우리는 이론적으로이 관계를 만들 수있는 방법이 있습니다. 그러나 파이썬 프로그래머로서, 당신의 뛰어난 지능은 이것이 짜증나고 더 잘 할 수 있다고 말하고 있습니다. 하이 파이브!

컨텐츠 유형 프레임 워크를 입력하십시오!

자, 이제 우리는 모델을 자세히 살펴보고보다 "재사용 가능하고"직관적 인 모델로 재 작업 할 것입니다. 우리의 외래 키 두 개를 제거하여 시작합시다.Comment모델 하고로 대체 해GenericForeignKey .

# ourapp.models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

...

class Comment(models.Model):
  author = models.ForeignKey(User)
  body = models.TextField(blank=True)
  content_type = models.ForeignKey(ContentType)
  object_id = models.PositiveIntegerField()
  content_object = GenericForeignKey()

그래서 무슨 일이야? 글쎄, 우리는 다른 모델과의 일반적인 관계를 위해 필요한 코드를 추가하고 추가했습니다. 공지 단지보다이 방법 GenericForeignKey도 있지만,이 ForeignKeyContentTypePositiveIntegerField에 대한이 object_id. 이 필드들은 장고에게 어떤 종류의 객체와 관련이 있고 그 객체의 id가 무엇인지 알려주기위한 것입니다. 실제로 Django는 이러한 관련 객체를 조회해야하기 때문에 이것이 의미가 있습니다.

글쎄, 그것은 파이썬과 같지 않습니다 ... 그것의 추악한!

귀도 반 로섬을 자랑스럽게 만들 수있는 완벽한 밀폐형의 직관적 인 코드를 찾고있을 것입니다 . 당신을 얻습니다. GenericRelation우리가 이것에 예쁜 활을 넣을 수 있도록 들판을 보자 .

# ourapp.models
from django.contrib.contenttypes.fields import GenericRelation

...

class Post(models.Model):
  author = models.ForeignKey(User)
  title = models.CharField(max_length=75)
  slug = models.SlugField(unique=True)
  body = models.TextField(blank=True)
  comments = GenericRelation('Comment')

class Picture(models.Model):
  author = models.ForeignKey(User)
  image = models.ImageField()
  caption = models.TextField(blank=True)
  comments = GenericRelation('Comment')

밤! 이와 같이이 두 모델에 대한 주석으로 작업 할 수 있습니다. 사실, 쉘 python manage.py shell에서 Django 프로젝트 디렉토리에서 입력 하십시오.

>>> from django.contrib.auth import get_user_model
>>> from ourapp.models import Picture, Post

# We use get_user_model() since we are referencing directly
User = get_user_model()

# Grab our own User object
>>> me = User.objects.get(username='myusername')

# Grab the first of our own pictures so we can comment on it
>>> pic = Picture.objects.get(author=me)

# Let's start making a comment for our own picture
>>> pic.comments.create(author=me, body="Man, I'm cool!")

# Let's go ahead and retrieve the comments for this picture now
>>> pic.comments.all()
[<Comment: "Man, I'm cool!">]

# Same for Post comments
>>> post = Post.objects.get(author=me)
>>> post.comments.create(author=me, body="So easy to comment now!")
>>> post.comments.all()
[<Comment: "So easy to comment now!"]

그렇게 간단합니다.

이러한 "일반적인"관계의 다른 실질적인 영향은 무엇입니까?

일반적인 외래 키를 사용하면 다양한 응용 프로그램간에 덜 관입적인 관계를 유지할 수 있습니다. 예를 들어, Comment 모델을 이름이 인 자체 앱으로 가져 왔다고 가정 해 봅시다 chatterly. 이제 noise_nimbus사람들이 음악을 저장하여 다른 사람들과 공유 할 수있는 다른 응용 프로그램을 만들고 싶습니다 .

노래에 댓글을 추가하려면 어떻게해야합니까? 우리는 일반적인 관계를 그릴 수 있습니다.

# noise_nimbus.models
from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models

from chatterly.models import Comment

# For a third time, we take the time to ensure custom Auth isn't overlooked
User = settings.AUTH_USER_MODEL

# Create your models here
class Song(models.Model):
  '''
  A song which can be commented on.
  '''
  file = models.FileField()
  author = models.ForeignKey(User)
  title = models.CharField(max_length=75)
  slug = models.SlugField(unique=True)
  description = models.TextField(blank=True)
  comments = GenericRelation(Comment)

나는 당신이 나에게 더 현실적인 적용 GenericForeignKeyGenericRelation분야 를 보여 주었던 것을 발견하고 싶었을 때 이것이 도움이 되길 바랍니다 .

이것이 사실이 너무 좋은가요?

인생의 모든 것과 마찬가지로 장단점이 있습니다. 더 많은 코드와 추상화를 추가 할 때마다 기본 프로세스가 더 무겁고 느려집니다. 일반 관계를 추가하면 결과를 스마트 캐시하고 시도하더라도 사실에 약간의 성능 저하가 추가 될 수 있습니다. 대체로 청결성과 단순성이 작은 성능 비용을 능가하는지 여부가 결정됩니다. 나에게 답은 백만 배입니다.

여기에 표시 한 것보다 더 많은 컨텐츠 유형 프레임 워크가 있습니다. 세밀한 수준과 자세한 사용법이 있지만 평균 개인의 경우 내 의견으로는 10 번 중 9 번 사용하는 방법입니다.

일반적인 관계자 (?)에주의하십시오!

다소 큰 경고 는을 사용할 때 적용된 ( )이 GenericRelation있는 모델 이 삭제되면 모든 관련 ( ) 객체도 삭제된다는 것입니다. 또는 적어도이 글을 쓰는 시점에서.GenericRelationPictureComment


11
그래서 내가 사용하는 경우 GenericRelationPostPicture나는이 사용할 필요가 없습니다 object_id, content_type그리고 content_objectComment?
avi

5
공식 Django 문서의 어딘가에 콘텐츠 형식 프레임 워크에 대한 명확한 설명이 있으면 좋을 것입니다. 나에 관해서는이 포트를 읽은 후에만이 프레임 워크가 무엇을하는지 깨달았습니다. 감사합니다.
prokher

2
조금 늦었지만 ... 콘텐츠 유형 프레임 워크를 사용하면 응용 프로그램이 제대로 확장되지 않을 수 있다고 들었습니다. 이것이 사실인지 아니면 사기인지 알려주십시오.
Karan Kumar

1
프로그래밍의 모든 것과 마찬가지로 Karan은 항상 "의존"이라고 답합니다. 콘텐츠 유형을 사용한다고 말합니다. 테이블 지향 SQL 시스템의 몇 가지 엄격한 기본 사항을 무시하는 것은 일종의 "타협"입니다. 앱을 조기에 최적화하지 마십시오! Django는 여러분이 원하는 방식으로 항상 원하는 차세대 응용 프로그램을 작성할 수 있도록 최선을 다하고 있습니다. 기능을 활용하십시오!
Chris Shelton

2
카란, 진실이있어 사용자의 알림을 추적하는 응용 프로그램을 만들고 있습니다. 각 알림에는 Google이 저장하는 다른 유형의 콘텐츠와 GenericForeignKey 관계가 있습니다. 사용자가 알림을 볼 때마다 ORM은 N 관련 쿼리를 실행하여 모든 관련 내용을 가져옵니다. 거의 이상적입니다.
Travis Mehlinger

-2

질문에 대한 직접적인 대답은 다음과 같습니다. (django 소스 코드에서) 다음은 RFC 2616 섹션 3.7에 따라 구문 분석되는 미디어 유형입니다.

그것은 'Content- type'httpd 헤더 를 따라 읽거나 수정하고 / 전달한다는 것을 말하는 눈물 입니다.

그러나 더 많은 사용 사례를 요구하고 있습니다. 두 가지 제안이 있습니다.

1 :이 코드를 검사

def index(request):
   media_type='text/html'
   if request.META.has_key('CONTENT_TYPE'):
      media_type = request.META['CONTENT_TYPE'].split(';')[0]

   if media_type.lower() == 'application/json':
      return HttpResponse("""{ "ResponseCode": "Success"}""", content_type="application/json; charset=UTF-8")

   return HttpResponse("<h1>regular old joe</h1>");

2 : 장고는 파이썬이라는 것을 기억하십시오. 따라서 파이썬 커뮤니티의 힘을 발휘합니다. django에 2 개의 멋진 RESTFul 플러그인이 있습니다. 따라서 토끼 전체가 얼마나 깊이 들어가는 지 확인하려면 체크 아웃하십시오.

나는 django-rest-framework tutorial을 통해 '다른 내용 / 유형에 대한 행동'을 구체적으로 다루는 것이 좋습니다. 참고 : content-type 헤더를 사용하여 restful API'version' 하는 것이 일반적 입니다.


1
그가 말하는 내용입니까? 또는 contenttypes 프레임 워크에? : docs.djangoproject.com/en/dev/ref/contrib/contenttypes
petkostas

1
예, 컨텐츠 유형 프레임 워크를 언급하고있었습니다. 나는 나 자신을 전달하는 충분한 일을하지 않았을 수 있습니다. 나는 상관없이 답변을 주셔서 감사합니다. 그 가치가 무엇인지, 그것이 내 질문이라면, 당신은 그것을 공원에서 떨어 뜨렸을 것입니다 =)
Chris Shelton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.