我真的很难掌握Django内容类型的概念.感觉非常hackish,并且最终反对Python倾向于做事情.话虽如此,如果我要使用Django,那么我必须在框架的范围内工作.
所以我来到这里想知道是否有人可以提供一个实际的现实世界示例,说明内容类型如何工作以及如何实现它.我所评论的几乎所有教程(主要是在博客上)并没有真正涵盖这个概念.他们似乎已经接受了Django文档遗留下来的地方(似乎无处可去).
Chr*_*ton 276
首先问问自己这个问题:"这些模型中的任何一个是否需要以与其他模型相同的方式相关联和/或我将在未来后期以不可预知的方式重用这些关系?" 我们之所以提出这个问题是因为这就是内容类型框架最擅长的:它创建了模型之间的通用关系.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)
Run Code Online (Sandbox Code Playgroud)
好的,所以我们确实有办法在理论上建立这种关系.但是,作为一名Python程序员,你的超级智慧告诉你这很糟糕,你可以做得更好.举手击掌!
那么,现在我们将仔细研究一下我们的模型,并将它们重新设计为更具"可重用性"和直观性.让我们首先摆脱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()
Run Code Online (Sandbox Code Playgroud)
所以发生了什么事?好吧,我们进入并添加了必要的代码以允许与其他模型的通用关系.请注意如何有不仅仅是一个更GenericForeignKey,更是一种 ForeignKey以ContentType和PositiveIntegerField为object_id.这些字段用于告诉Django与此对象相关的对象类型以及该对象的id是什么.实际上,这是有道理的,因为Django将需要两者来查找这些相关对象.
您可能正在寻找能够让Guido van Rossum自豪的气密,一尘不染,直观的代码.我找到了你 让我们来看看这个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')
Run Code Online (Sandbox Code Playgroud)
巴姆!就像那样,你可以使用这两个模型的评论.实际上,让我们继续在我们的shell(python manage.py shell从Django项目目录中输入)中执行此操作.
>>> from django.contrib.auth import get_user_model
>>> from ourapp.models import Picture
# 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!">]
Run Code Online (Sandbox Code Playgroud)
就这么简单.
通用外键允许各种应用程序之间的侵入性较小的关系.例如,假设我们将评论模型拉出到它自己的应用程序中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)
Run Code Online (Sandbox Code Playgroud)
我希望你们发现这很有帮助,因为我喜欢看到一些东西,这些东西向我展示了更真实的应用GenericForeignKey和GenericRelation领域.
与生活中的任何事物一样,有利有弊.无论何时添加更多代码和更多抽象,底层进程都会变得更重,速度更慢.添加泛型关系可以增加一点性能阻尼,尽管它会尝试并智能缓存其结果.总而言之,它归结为清洁度和简洁性是否超过了小的性能提升.对我来说,答案是百万次是的.
内容类型框架比我在此处显示的更多.有一个完整的粒度级别和更详细的使用,但对于普通人来说,这就是我认为你将在10次中使用它的方式.
一个相当大的警告是当你使用a时GenericRelation,如果删除了具有GenericRelationapplied(Picture)的模型,那么所有related(Comment)对象也将被删除.或至少截至撰写本文时.
| 归档时间: |
|
| 查看次数: |
30238 次 |
| 最近记录: |