Vì vậy, bạn muốn sử dụng khung Kiểu nội dung cho công việc của bạn?
Bắt đầu bằng cách tự hỏi mình câu hỏi này: "Có bất kỳ mô hình nào trong số những mô hình này cần phải liên quan theo cùng một cách với các mô hình khác không và / hoặc tôi sẽ sử dụng lại các mối quan hệ này theo những cách chưa được giải quyết sau này?" Lý do tại sao chúng tôi đặt câu hỏi này là vì đây là khung công tác Kiểu nội dung tốt nhất: nó tạo ra các mối quan hệ chung giữa các mô hình. Blah blah, hãy đi sâu vào một số mã và xem ý tôi là gì.
# 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)
Được rồi, vì vậy chúng tôi có một cách để lý thuyết tạo mối quan hệ này. Tuy nhiên, là một lập trình viên Python, trí tuệ vượt trội của bạn đang nói với bạn điều này thật tệ và bạn có thể làm tốt hơn. Đập tay!
Nhập khung loại nội dung!
Chà, bây giờ chúng ta sẽ xem xét kỹ các mô hình của chúng ta và làm lại chúng để "tái sử dụng" và trực quan hơn. Hãy bắt đầu bằng cách loại bỏ hai khóa ngoại trên Comment
mô hình của chúng tôi và thay thế chúng bằng một 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()
Vậy chuyện gì đã xảy ra? Vâng, chúng tôi đã đi vào và thêm mã cần thiết để cho phép có mối quan hệ chung với các mô hình khác. Thông báo như thế nào có nhiều hơn chỉ là một GenericForeignKey
, mà còn là một ForeignKey
đến ContentType
và một PositiveIntegerField
cho object_id
. Các trường này là để cho Django biết loại đối tượng này có liên quan đến và id là gì cho đối tượng đó. Trong thực tế, điều này có ý nghĩa bởi vì Django sẽ cần cả hai để tra cứu các đối tượng liên quan này.
Chà, nó không giống Python lắm ... xấu quá!
Có lẽ bạn đang tìm kiếm mã trực quan, không tì vết, trực quan sẽ khiến Guido van Rossum tự hào. Tôi hiểu bạn Chúng ta hãy nhìn vào GenericRelation
lĩnh vực này để chúng ta có thể đặt một cái cung đẹp trên này.
# 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')
Bế! Cũng giống như vậy, bạn có thể làm việc với các Nhận xét cho hai mô hình này. Trong thực tế, hãy tiếp tục và làm điều đó trong vỏ của chúng tôi (nhập python manage.py shell
từ thư mục dự án Django của bạn).
>>> 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!"]
Nó đơn giản mà.
Ý nghĩa thực tế khác của các mối quan hệ "chung chung" này là gì?
Khóa ngoại chung cho phép mối quan hệ ít xâm phạm hơn giữa các ứng dụng khác nhau. Ví dụ: giả sử chúng tôi đã kéo mô hình Nhận xét ra thành ứng dụng riêng có tên chatterly
. Bây giờ chúng tôi muốn tạo một ứng dụng khác có tên là noise_nimbus
nơi mọi người lưu trữ nhạc của họ để chia sẻ với người khác.
Nếu chúng ta muốn thêm ý kiến cho những bài hát đó thì sao? Chà, chúng ta chỉ có thể vẽ một mối quan hệ chung chung:
# 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)
Tôi hy vọng các bạn thấy điều này hữu ích vì tôi rất thích đã bắt gặp một cái gì đó cho tôi thấy ứng dụng GenericForeignKey
và GenericRelation
lĩnh vực thực tế hơn .
Điều này là quá tốt để là sự thật?
Như với bất cứ điều gì trong cuộc sống, có những ưu và nhược điểm. Bất cứ khi nào bạn thêm nhiều mã hơn và trừu tượng hơn, các quy trình cơ bản trở nên nặng hơn và chậm hơn một chút. Thêm các mối quan hệ chung có thể thêm một chút bộ giảm hiệu suất mặc dù thực tế nó sẽ thử và thông minh lưu trữ kết quả của nó. Nói chung, vấn đề là sự sạch sẽ và đơn giản có cao hơn chi phí hiệu suất nhỏ hay không. Đối với tôi, câu trả lời là một triệu lần có.
Có nhiều khung công tác Kiểu nội dung hơn tôi đã hiển thị ở đây. Có một mức độ chi tiết và mức độ sử dụng dài dòng hơn, nhưng đối với cá nhân trung bình, đây là cách bạn sẽ sử dụng nó 9 trên 10 lần theo ý kiến của tôi.
Quan hệ chung (?) Hãy coi chừng!
Một cảnh báo khá lớn là khi bạn sử dụng a GenericRelation
, nếu mô hình đã GenericRelation
áp dụng ( Picture
) bị xóa, tất cả các Comment
đối tượng ( ) có liên quan cũng sẽ bị xóa. Hoặc ít nhất là tại thời điểm viết bài này.