咱們在網上po一段散文詩也能夠po一張旅途的風景圖,文字能夠被評論,圖片也能夠被評論。咱們須要在數據庫中建表存儲這些數據,咱們可能會設計出下面這樣的表結構。數據庫
class Post(models.Model): """帖子表""" author = models.ForeignKey(User) title = models.CharField(max_length=72) class Picture(models.Model): """圖片表""" author = models.ForeignKey(User) image = models.ImageField() class Comment(models.Model): """評論表""" author = models.ForeignKey(User) content = models.TextField() post = models.ForeignKey(Post, null=True, blank=True, on_delete=models.CASCADE) picture = models.ForeignKey(Picture, null=True, blank=True, on_delete=models.CASCADE)
這表結構看起來不太簡潔,咱們畫個圖來看一下:django
能用是能用,可是評論表有點冗餘啊。好多列都空着呢啊!app
咱們優化一下,咱們在評論表裏不直接外鍵關聯 文字和圖片,而是存儲一下關聯的表名和字段,這樣就好不少了。工具
看下圖:post
那咱們不妨步子再大一點,再往前走一步試試,由於表名在評論裏面重複了不少次,咱們徹底能夠把Django項目中的表名都存儲在一個表裏面。而後評論表裏外鍵關聯這個表就能夠了。測試
class Comment(models.Model): """評論表""" author = models.ForeignKey(User) content = models.TextField() content_type = models.ForeignKey(ContentType) # 外鍵關聯django_content_type表 object_id = models.PositiveIntegerField() # 關聯數據的主鍵 content_object = GenericForeignKey('content_type', 'object_id')
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_contenttype.settings") import django django.setup() from app01.models import Post, Picture, Comment from django.contrib.auth.models import User # 準備測試數據 user_1 = User.objects.create_user(username='aaa', password='123') user_2 = User.objects.create_user(username='bbb', password='123') user_3 = User.objects.create_user(username='ccc', password='123') post_1 = Post.objects.create(author=user_1, title='Python入門教程') post_2 = Post.objects.create(author=user_2, title='Python進階教程') post_3 = Post.objects.create(author=user_1, title='Python入土教程') picture_1 = Picture.objects.create(author=user_1, image='小姐姐01.jpg') picture_2 = Picture.objects.create(author=user_1, image='小姐姐02.jpg') picture_3 = Picture.objects.create(author=user_3, image='小哥哥01.jpg') # 給帖子建立評論數據 comment_1 = Comment.objects.create(author=user_1, content='好文!', content_object=post_1) # 給圖片建立評論數據 comment_2 = Comment.objects.create(author=user_2, content='好美!', content_object=picture_1)
from django.contrib.contenttypes.fields import GenericRelation
class Post(models.Model): """帖子表""" author = models.ForeignKey(User) title = models.CharField(max_length=72) comments = GenericRelation('Comment') # 支持反向查找評論數據(不會在數據庫中建立字段) class Picture(models.Model): """圖片表""" author = models.ForeignKey(User) image = models.ImageField() comments = GenericRelation('Comment') # 支持反向查找評論數據(不會在數據庫中建立字段)
查詢示例:優化
post_1 = Post.objects.filter(id=1).first() comment_list = post_1.comments.all()