Django内容类型的工作原理 [英] How exactly do Django content types work?

查看:99
本文介绍了Django内容类型的工作原理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我讨厌浪费人们的时间。这是我在这里的第一篇文章,真的只是在广泛搜索一个答案的日子之后的最后手段。我真的很难把握Django内容类型的概念。感觉非常黑客,最终反对Python倾向于做什么。话虽如此,如果我要使用Django,那么我必须在框架的范围内工作。



所以我来到这里想知道是否有人可以一个内容类型如何工作的实际现实世界的例子,以及如何实现它。几乎所有的教程(主要是在博客上)我已经审查过,不能做一个真正涵盖这个概念的伟大工作。他们似乎拿起了Django文档离开的地方(似乎没有地方)。



我很欣赏你们在这里做什么,我真的很想看看你的

解决方案

所以你想在你的工作中使用内容类型框架?



首先询问自己这个问题:这些模型中的任何一个需要与其他模型相同的方式进行相关关系,和/或者是否会在未来的路途中重新使用这些关系?我们提出这个问题的原因是因为这是内容类型框架最好的:它创建模型之间的通用关系。 Blah blah,让我们来看看一些代码,看看我的意思。

 #ourapp.models 
from django.conf导入设置
从django.db导入模型

#分配用户模型,以防交换
用户=设置.AUTH_USER_MODEL

#在这里创建你的模型
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)

类注释(models.Model):
author = models.ForeignKey(用户)
body = models.TextField(blank = True)
post = models.ForeignKey(Post)
picture = models.ForeignKey(Picture)

好的,我们确实有一种理论上创造这种关系的方法。然而,作为一个Python程序员,你的卓越智慧告诉你这个很糟糕,你可以做得更好。高五!



输入内容类型框架



嗯,现在我们要关闭看看我们的模型,并重新使用它们,使其更加可重用和直观。我们先从我们的评论模型中删除两个外键,然后用一个 GenericForeignKey 替换它们。

 #weapp.models 
from django.contrib.contenttypes.fields import来自django.contrib.contenttypes的GenericForeignKey
。模型导入ContentType

...

类注释(models.Model):
author = models.ForeignKey(User)
body = models。 TextField(blank = True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
/ pre>

那么发生了什么事?那么,我们进去并添加了必要的代码,以允许与其他模型的通用关系。请注意,不仅仅是一个 GenericForeignKey ,而且还有一个 ForeignKey ContentType PositiveIntegerField object_id 。这些字段用于告诉Django与此对象有何类型的对象以及该对象的id。实际上,这是有道理的,因为Django将需要同时查找这些相关的对象。



嗯,这不是很像Python的...它有点丑陋!



您可能正在寻找气密,一尘不染,直观的代码,使 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 =
comment = GenericRelation('Comment')

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

Bam!就像这样,你可以使用这两个模型的评论。事实上,我们继续在我们的shell中(从你的Django项目目录中输入 python manage.py shell )。

 >>> from django.contrib.auth import get_user_model 
>>>从我们的app.models import Picture

#我们使用get_user_model(),因为我们直接引用
User = get_user_model()

#抓住我们自己的User对象
>>>> me = User.objects.get(username ='myusername')

#抓住我们自己的第一张图片,以便我们对其进行评论
>>> pic = Picture.objects.get(author = my)

#我们开始为自己的图片发表评论
>>> pic.comments.create(作者=我,身体=男人,我很好!)

#现在我们继续检索这张照片的评论
>> > pic.comments.all()
[<评论:男人,我很好!>]

这很简单。



这些通用关系的其他实际含义是什么?


$ b $通用外键允许各种应用程序之间的干涉关系较少。例如,假设我们将评论模型引入到自己的名为 chatterly 的应用程序中。现在,我们要创建另一个名为 noise_nimbus 的应用程序,人们可以将他们的音乐存储在与他人分享。



想给这些歌曲添加评论?嗯,我们可以绘制一个通用的关系:

  #_nextbus.models 
从django.conf导入设置
从django.contrib.contenttypes.fields导入GenericRelation
从django.db导入模型

从chatterly.models import注释

#第三次,我们花时间确保自定义Auth不被忽视
User = settings.AUTH_USER_MODEL

#在这里创建您的模型
类Song(models.Model):
'''
可以评论的歌曲。
'''
file = models.FileField()
author = models.ForeignKey(User)
title = models.CharField(max_length = 75)
slug = model.SlugField(unique = True)
description = models.TextField(blank = True)
comments = GenericRelation(Comment)

我希望你们发现这有帮助,因为我会喜欢碰到一些让我看到更实际的应用程序 GenericForeignKey GenericRelation 字段。



这太好了吗?



与生活中的任何东西一样,有利弊。无论何时添加更多的代码和更多的抽象,底层进程变得更重,有点慢。添加通用关系可以添加一点性能阻尼器,尽管它将尝试智能缓存其结果。总而言之,归结于清洁度和简单性是否超过了小的性能提升。对我来说,答案是百万次是的。



与我在这里显示的内容类型框架相比,还有更多的内容类型框架。有一个完整的粒度级别和更详细的使用,但对于一般的个人来说,这是你将如何使用它9次10次在我看来。



通用关系者(?)请注意!



相当大的警告是当您使用 GenericRelation ,如果应用了 GenericRelation 的模型( Picture )被删除,所有相关(评论)对象也将被删除。或至少在撰写本文时。


I hate wasting people's time. This is my first post here and it is really only a last resort after days of searching extensively for an answer. I'm really having a difficult time grasping the concept of Django's content types. It feels very hackish and, ultimately, against how Python tends to do things. That being said, if I'm going to use Django then I have to work within the confines of the framework.

So I'm coming here wondering if anyone can give a practical real world example of how a content type works and how you would implement it. Almost all the tutorials (mostly on blogs) I have reviewed don't do a great job really covering the concept. They seem to pick up where the Django documentation left off (what seems like nowhere).

I appreciate what you guys do here and I'm really anxious to see what you have to say.

解决方案

So you want to use the Content Types framework on your work?

Start by asking yourself this question: "Do any of these models need to be related in the same way to other models and/or will I be reusing these relationships in unforseen ways later down the road?" The reason why we ask this question is because this is what the Content Types framework does best: it creates generic relations between models. Blah blah, let's dive into some code and see what I mean.

# 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)

Okay, so we do have a way to theoretically create this relationship. However, as a Python programmer, your superior intellect is telling you this sucks and you can do better. High five!

Enter the Content Types framework!

Well, now we're going to take a close look at our models and rework them to be more "reusable" and intuitive. Let's start by getting rid of the two foreign keys on our Comment model and replace them with a 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()

So, what happened? Well, we went in and added the necessary code to allow for a generic relation to other models. Notice how there is more than just a GenericForeignKey, but also a ForeignKey to ContentType and a PositiveIntegerField for the object_id. These fields are for telling Django what type of object this is related to and what the id is for that object. In reality, this makes sense because Django will need both to lookup these related objects.

Well, that's not very Python-like... its kinda ugly!

You are probably looking for air-tight, spotless, intuitive code that would make Guido van Rossum proud. I get you. Let's look at the GenericRelation field so we can put a pretty bow on this.

# 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')

Bam! Just like that you can work with the Comments for these two models. In fact, let's go ahead and do that in our shell (type python manage.py shell from your Django project directory).

>>> 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!">]

It's that simple.

What are the other practical implications of these "generic" relations?

Generic foreign keys allow for less intrusive relations between various applications. For example, let's say we pulled the Comment model out into it's own app named chatterly. Now we want to create another application named noise_nimbus where people store their music to share with others.

What if we want to add comments to those songs? Well, we can just draw a generic relation:

# 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)

I hope you guys found this helpful as I would have loved to have come across something that showed me the more realistic application of GenericForeignKey and GenericRelation fields.

Is this too good to be true?

As with anything in life, there are pros and cons. Anytime you add more code and more abstraction, the underlying processes becomes heavier and a bit slower. Adding generic relations can add a little bit of a performance dampener despite the fact it will try and smart cache its results. All in all, it comes down to whether the cleanliness and simplicity outweighs the small performance gains. For me, the answer is a million times yes.

There is more to the Content Types framework than I have displayed here. There is a whole level of granularity and more verbose usage, but for the average individual, this is how you will be using it 9 out of 10 times in my opinion.

Generic relationizers(?) beware!

A rather large caveat is that when you use a GenericRelation, if the model which has the GenericRelation applied (Picture) is deleted, all related (Comment) objects will also be deleted. Or at least as of the time of this writing.

这篇关于Django内容类型的工作原理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆