Django【ORM】:GenericForeignKey的使用

一、概述

Django为了帮助我们解决关系型数据库多个表之间享用共同外键的问题时,提供了GenericForeignKey模型字段,虽然性能上有些许损耗,但是逻辑清楚、比较易用。

二、GenericForeignKey的使用

1、Model层使用通用外键:
这里为了实现多个不同情景的模型下(如文章、集体讨论等)下的评论Comment,可使用GenericForeignKey。(不过一般情况下通用外键更适合于如 点赞数、浏览数这样的情景)

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.auth.models import ContentType
...
class Comment(models.Model):
    """Comment aimed at: Discussion, Article and User's comment"""
    user_belong = models.ForeignKey(to=User, on_delete=models.CASCADE)
    content = models.CharField(max_length=100, verbose_name="评论内容")
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="评论时间")

    
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) #ContentType为Django自带模型。
    object_id = models.PositiveIntegerField()  #注意object_id必须设置为整数字段,其代表针对Model实例的id
    
    #使用GenericForeignKey,该字段自动接受content_type和object_id作为它的参数!
    content_object = GenericForeignKey()
    ...


2、GenericForeignKey的简单操作
(1)增加一条评论:在view模块的add_comment()函数中针对Article model的一个实例增加一条评论:

def add_comment(request):
    """add a comment to Article"""
    target = request.POST.get('target')
    article = Article.objects.get(id=target)

    form = CommentForm(request.POST)
    if form.is_valid():
        new_comment = form.save(commit=False)
        new_comment.content_object = article  #重点在这里!
        new_comment.user_belong = request.user
        new_comment.save()
        return HttpResponseRedirect(reverse('learning_logs:article',args=target))
        ...

(2)根据文章查询评论(正向查询):

    快捷方法:

    为了更方便的查询一篇文章下的所有评论,可在ArticleModel中增加:

from django.contrib.contenttypes.fields import GenericRelation
class Article(models.Model):
...
	comment_info = GenericRelation(Comment)
...

    然后便可根据此直接查询:

class Comment(models.Model):
    @classmethod
    def get_comments(cls, target):
        article = amodel.Article.objects.get(id=target) #先获取特定的文章对象,注意是对象
        comments = article.comment_info.all() #利用上述的GeneRelation直接得到该文章的所有评论。
        return comments

    通用方法:

from django.contrib.auth.models import ContentType
class Comment(models.Model):
...
   def get_comments(self, article_id):
        model_type = ContentType.objects.get_for_model(Comment)
        inner_comments = Comment.objects.filter(content_type=model_type, object_id=article_id)
        return comments
...

三、其它

在完成模型部分的设计并且完成数据库迁移之后,在数据库中可以看到有cotente_type这张表它是创建项目时Django自动生成的表):
在这里插入图片描述在这里插入图片描述
再来看看comment表: 注意这里的object_id和content_id属性,分别对应着之前Comment类中的object_idcontent_type属性。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44683653/article/details/106432018