Django contenttypes 框架详解(小结)
Django contenttypes 框架是 Django 框架提供的一种解耦的途径,可以实现通用化的外键或者多态关系,本文将介绍该框架的详细使用方法。
什么是 contenttypes
contenttypes 是 Django 提供的库,可以在我们的应用中使用通用的外键。通常情况下,使用外键指向一个特定的模型对象,但是有些时候我们会需要使用对象的通用关联,这就是 contenttypes 库的作用。
相关概念
在使用 contenttypes 库时,需要了解以下两个关键概念:
-
ContentType
:代表一个模型的类型,所有已经安装的模型都会在 ContentType 中注册,每个 ContentType 对应一个 app 和一个 model。 -
GenericForeignKey
:代表一个通用的外键,可以关联到任何一个 model 实例。
在使用这两个概念时,我们需要先在模型中继承 models.Model
类,然后在需要通用外键的字段中,使用 models.ForeignKey
和 models.ManyToManyField
类型,来指定使用 GenericForeignKey。
代码示例
下面给出示例代码,使用 contenttypes 实现一个通用的评论系统:
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.urls import reverse
class Comment(models.Model):
"""
评论模型
"""
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
# 评论内容
text = models.TextField('评论内容')
# 评论时间
comment_time = models.DateTimeField(auto_now=True)
def __str__(self):
return self.text
class Meta:
ordering = ['-comment_time']
class Article(models.Model):
"""
文章模型
"""
title = models.CharField('标题', max_length=100)
content = models.TextField('内容')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[self.id])
class CommentForm(forms.ModelForm):
"""
评论表单
"""
class Meta:
model = Comment
fields = ['text']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['text'].widget.attrs.update({'class': 'form-control', 'placeholder': '请填写评论'})
# 在视图函数中使用通用外键
def article_detail(request, id):
article = get_object_or_404(Article, id=id)
# 获取该文章所有已发布的评论
content_type = ContentType.objects.get_for_model(Article)
comments = Comment.objects.filter(content_type=content_type, object_id=article.id)
if request.method == 'POST':
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
comment = comment_form.save(commit=False)
comment.content_object = article
comment.save()
# 重定向到文章详情页
return redirect(article.get_absolute_url() + '#comment_list')
else:
comment_form = CommentForm()
context = {
'article': article,
'comments': comments,
'comment_form': comment_form,
}
return render(request, 'article_detail.html', context)
上述代码实现的效果是,在文章详情页面展示该文章所有已经发布的评论,并支持用户添加新评论。
总结
使用 contenttypes 框架可以极大地简化模型之间的关联操作,同时大大提高了代码的复用性。在实际应用中,可以根据实际需要使用通用外键来构建复杂的关联系统。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Django contenttypes 框架详解(小结) - Python技术站