真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

什么是Djangocontenttypes框架-創(chuàng)新互聯(lián)

創(chuàng)新互聯(lián)www.cdcxhl.cn八線動(dòng)態(tài)BGP香港云服務(wù)器提供商,新人活動(dòng)買多久送多久,劃算不套路!

創(chuàng)新互聯(lián)擁有一支富有激情的企業(yè)網(wǎng)站制作團(tuán)隊(duì),在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)深耕10年,專業(yè)且經(jīng)驗(yàn)豐富。10年網(wǎng)站優(yōu)化營銷經(jīng)驗(yàn),我們已為數(shù)千家中小企業(yè)提供了成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)解決方案,按需開發(fā)網(wǎng)站,設(shè)計(jì)滿意,售后服務(wù)無憂。所有客戶皆提供一年免費(fèi)網(wǎng)站維護(hù)!

什么是Django contenttypes框架?很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

什么是Django ContentTypes?

Django ContentTypes是由Django框架提供的一個(gè)核心功能,它對當(dāng)前項(xiàng)目中所有基于Django驅(qū)動(dòng)的model提供了更高層次的抽象接口。

然而,對于Django ContentTypes不熟悉的人來說,上面這句話說了跟沒說一樣,因此,筆者將一步一步解釋Django ContentTypes在Django框架中做了什么,以及如何使用Django ContentTypes。

當(dāng)然,如果對于ContentTypes有了初步了解而只是不了解它的應(yīng)用場景,可以直接查閱以下這兩個(gè)鏈接:

Django official documentation:The contenttypes framework

stackoverflow: How exactly do Django content types work?

Django ContentTypes做了什么?

當(dāng)使用django-admin初始化一個(gè)django項(xiàng)目的時(shí)候,可以看到在默認(rèn)的INSTALL_APPS已經(jīng)包含了django.contrib.contenttypes:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

而且注意django.contrib.contenttypes是在django.contrib.auth之后,這是因?yàn)閍uth中的permission系統(tǒng)是根據(jù)contenttypes來實(shí)現(xiàn)的。

筆者緊接著查閱了一下django.contrib.contenttypes.models文件:

class ContentType(models.Model):
    app_label = models.CharField(max_length=100)
    model = models.CharField(_('python model class name'), max_length=100)
    objects = ContentTypeManager()
    class Meta:
        verbose_name = _('content type')
        verbose_name_plural = _('content types')
        db_table = 'django_content_type'
        unique_together = (('app_label', 'model'),)
    def __str__(self):
        return self.name

大家可以看到ContentType就是一個(gè)簡單的django model,而且它在數(shù)據(jù)庫中的表的名字為django_content_type。

有經(jīng)驗(yàn)的Django開發(fā)者對于這個(gè)表的名字一般都不會(huì)陌生,在第一次對Django的model進(jìn)行migrate之后,就可以發(fā)現(xiàn)在數(shù)據(jù)庫中出現(xiàn)了一張默認(rèn)生成的名為django_content_type的表。

如果沒有建立任何的model,默認(rèn)django_content_type是這樣的:

sqlite> select * from django_content_type;
1|admin|logentry
2|auth|group
3|auth|user
4|auth|permission
5|contenttypes|contenttype
6|sessions|session

因此,django_content_type記錄了當(dāng)前的Django項(xiàng)目中所有model所屬的app(即app_label屬性)以及model的名字(即model屬性)。

當(dāng)然,django_content_type并不只是記錄屬性這么簡單,在一開始的時(shí)候筆者就提及了contenttypes是對model的一次封裝,因此可以通過contenttypes動(dòng)態(tài)的訪問model類型,而不需要每次import具體的model類型。

·ContentType實(shí)例提供的接口

    ·ContentType.model_class()

        ·獲取當(dāng)前ContentType類型所代表的模型類

    ·ContentType.get_object_for_this_type()

        ·使用當(dāng)前ContentType類型所代表的模型類做一次get查詢

·ContentType管理器(manager)提供的接口

    ·ContentType.objects.get_for_id()

        ·通過id尋找ContentType類型,這個(gè)跟傳統(tǒng)的get方法的區(qū)別就是它跟get_for_model共享一個(gè)緩存,因此更為推薦。

    ·ContentType.objects.get_for_model()

        ·通過model或者model的實(shí)例來尋找ContentType類型

Django ContentTypes的使用場景

Permission對ContentType的使用

在之前,筆者簡單地提及了auth中Permission有涉及到對ContentType的使用,下面來看一下Permission的model源碼:

class Permission(models.Model):
    """
    The permissions system provides a way to assign permissions to specific
    users and groups of users.
    The permission system is used by the Django admin site, but may also be
    useful in your own code. The Django admin site uses permissions as follows:
        - The "add" permission limits the user's ability to view the "add" form
          and add an object.
        - The "change" permission limits a user's ability to view the change
          list, view the "change" form and change an object.
        - The "delete" permission limits the ability to delete an object.
    Permissions are set globally per type of object, not per specific object
    instance. It is possible to say "Mary may change news stories," but it's
    not currently possible to say "Mary may change news stories, but only the
    ones she created herself" or "Mary may only change news stories that have a
    certain status or publication date."
    Three basic permissions -- add, change and delete -- are automatically
    created for each Django model.
    """
    name = models.CharField(_('name'), max_length=255)
    content_type = models.ForeignKey(ContentType,models.CASCADE,verbose_name=_('content type'),)
    codename = models.CharField(_('codename'), max_length=100)
    objects = PermissionManager()
    class Meta:
        verbose_name = _('permission')
        verbose_name_plural = _('permissions')
        unique_together = (('content_type', 'codename'),)
        ordering = ('content_type__app_label', 'content_type__model','codename')

大家可以看到Permission模型中設(shè)置了一個(gè)對ContentType的外鍵,這意味著每一個(gè)Permission的實(shí)例都具有關(guān)于一個(gè)ContentType的id作為外鍵,而ContentType的id恰恰代表著一個(gè)Model。

回想Permission模型在初始化的時(shí)候發(fā)生了什么,它為每個(gè)模型設(shè)置了三個(gè)權(quán)限,分別是add,change以及delete,那么它是如何跟每個(gè)模型聯(lián)系起來的呢?就是通過一個(gè)到ContentType的外鍵。

大家可以看一下Permission表,其中第二行就是content_type,然后將主鍵于django_content_type對比:

sqlite> select * from auth_permission;
1|1|add_logentry|Can add log entry
2|1|change_logentry|Can change log entry
3|1|delete_logentry|Can delete log entry
4|2|add_group|Can add group
5|2|change_group|Can change group
6|2|delete_group|Can delete group
7|3|add_user|Can add user
8|3|change_user|Can change user
9|3|delete_user|Can delete user
10|4|add_permission|Can add permission
11|4|change_permission|Can change permission
12|4|delete_permission|Can delete permission
13|5|add_contenttype|Can add content type
14|5|change_contenttype|Can change content type
15|5|delete_contenttype|Can delete content type
16|6|add_session|Can add session
17|6|change_session|Can change session
18|6|delete_session|Can delete session

如此,Permission模型借助ContentType表達(dá)了對一個(gè)model的權(quán)限操作。

ContentType的通用類型

筆者將引用在頂部的stackoverflow中回答的例子講述對通用類型的理解。

假設(shè)以下的應(yīng)用場景:

from django.db import models
from django.contrib.auth.models import User
# 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, null=True)
    picture = models.ForeignKey(Picture, null=True)

注意筆者這里跟原回答做了一些更改,在原回答中Comment中沒有null的選項(xiàng),筆者覺得回答者真正要表達(dá)的是Comment是分別和Picture或者Post中其中一個(gè)對應(yīng)即可,一個(gè)Comment并不既需要Post又需要Picture才能建立,可能是回答者寫錯(cuò)沒注意的緣故。

當(dāng)筆者對以上model進(jìn)行migrate之后,發(fā)現(xiàn)Comment表中的foreignkey是可以被設(shè)置為null的。

那么,如何通過Contenttype框架對以上代碼進(jìn)行改進(jìn)呢?

ContentType提供了一種GenericForeignKey的類型,通過這種類型可以實(shí)現(xiàn)在Comment對其余所有model的外鍵關(guān)系。

修改后的Comment模型如下:

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

在這里,通過使用一個(gè)content_type屬性代替了實(shí)際的model(如Post,Picture),而object_id則代表了實(shí)際model中的一個(gè)實(shí)例的主鍵,其中,content_type和object_id的字段命名都是作為字符串參數(shù)傳進(jìn)content_object的。即:

content_object = fields.GenericForeignKey('content_type', 'object_id')

筆者先準(zhǔn)備一些測試用的數(shù)據(jù):

user = User.objects.create_user(username='user1', password='2333')
post = Post.objects.create(author=user,title='title1',slug=slugify('title1'),body='')
picture = Picture.objects.create(author=user,image="http://www.picture1.com",caption='picture1')

接著在shell中創(chuàng)建Comment:

>>> from foreign.models import Post, Picture, Common
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username='user1')
>>> post = Post.objects.get(title='title1')
>>> c = Comment.objects.create(author=user, body='', content_object=post)
>>> c

>>> c.content_type

>>> c.object_id
1
>>> picture = Picture.objects.get(caption='picuture1')
>>> c = Comment.objects.create(author=user, body='', content_object=picture)
>>> c.content_type

>>> c.object_id
1

在django中,也提供從諸如Post,Picture訪問Comment的查詢,通過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)
    comment = GenericRelation('Comment')

值得注意的是,如果在Post中定義了GenericRelation,刪除了一個(gè)實(shí)例,在Comment中所有的相關(guān)實(shí)例也會(huì)被刪除,GenericForeignKey不支持設(shè)置on_delete參數(shù)。

因此,如果對級聯(lián)刪除不滿意的話就不要設(shè)置GenericRelation。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。


文章標(biāo)題:什么是Djangocontenttypes框架-創(chuàng)新互聯(lián)
分享鏈接:http://weahome.cn/article/igsdd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部