我有一个“Entry”模型,包含一个GenericForeignKey:
class Entry(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
不同内容模型,如“注意”和“文件”:
class Note(models.Model):
title = models.CharField(max_length=255)
text = models.TextField()
class File(models.Model):
title = models.CharField(max_length=255)
file_field = models.FileField('File', upload_to='files')
description = models.TextField(blank=True)
如果存储它们,则会自动创建一个新的“条目”,因此我可以按以下列出所有内容:
Entry.objects.all()
现在我正在寻找一种方法来编写视图和模板,它应该以任意顺序列出所有Entrys及其详细信息(例如按日期)。怎么办呢?
是否可以将部分模板与特定模型相关联?模板如何知道如何在列表中显示特定实例?
整个而非简化的models.py看起来像这样:
from django.db.models.signals import post_save, pre_delete
import datetime
class Entry(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
def title(self):
return self.content_object.title
def __unicode__(self):
return self.title()
class DateModel(models.Model):
""" A model for basic date awareness """
modified_date = models.DateTimeField(blank=True, null=True)
created_date = models.DateTimeField(blank=True)
class Meta:
abstract = True
ordering = ['-created_date']
def save(self, *args, **kwargs):
if not self.pk:
self.created_date = datetime.datetime.now()
else:
self.modified_date = datetime.datetime.now()
return super(DateModel, self).save(*args, **kwargs)
class Tag(DateModel):
name = models.CharField(max_length=51, unique=True)
def __unicode__(self):
return self.name
class Notebook(models.Model):
name = models.CharField(max_length=50, unique=True)
description = models.TextField(blank=True)
def __unicode__(self):
return self.name
class EntryModel(DateModel):
"""All Entry models are inherited from this abstract class"""
title = models.CharField(max_length=255)
notebook = models.ForeignKey(Notebook, blank=True, null=True)
tags = models.ManyToManyField(Tag, blank=True, null=True)
class Meta:
abstract = True
def __unicode__(self):
return self.title
######## Begin: Entry Classes ########
class Memo(EntryModel):
text = models.TextField()
def save(self, *args, **kwargs):
if self.title == '-' or self.title == '':
if len(self.text) > 20:
self.title = self.text[:17]+'...'
else:
self.title = self.text
return super(EntryModel, self).save(*args, **kwargs)
class File(EntryModel):
file_field = models.FileField('File', upload_to='files')
description = models.TextField(blank=True)
######## End: Entry Classes ########
def create_entry(sender, **kwargs):
"""Handler for post_save signal to create new Entry"""
if 'created' in kwargs:
if kwargs['created']:
instance = kwargs['instance']
ctype = ContentType.objects.get_for_model(instance)
entry = Entry.objects.get_or_create(
content_type=ctype,
object_id=instance.id)
def delete_entry(sender, **kwargs):
"""Handler for pre_delete signal to delete related Entry"""
instance = kwargs['instance']
ctype = ContentType.objects.get_for_model(instance)
entry = Entry.objects.get(
content_type=ctype,
object_id=instance.id)
entry.delete()
# Connect handler to post_save signal
entry_classes = EntryModel.__subclasses__()
for cls in entry_classes:
post_save.connect(create_entry, sender=cls)
pre_delete.connect(delete_entry, sender=cls)
答案 0 :(得分:0)
如评论中所述,您的参赛作品是笔记或文件。因此IMO模型继承更适合您的用例。你的models.py看起来像这样:
models.py 来自django.contrib.contenttypes.models import ContentType
class Entry(models.Model):
title = models.CharField(max_length=255)
real_type = models.ForeignKey(ContentType, editable=False)
created = models.DateTimeField(auto_now_add=True, editable=False, verbose_name='creation date')
def save(self):
if not self.id:
self.real_type = self._get_real_type()
self.created = datetime.today()
self.modified = datetime.today()
super(ListType, self).save()
def _get_real_type(self):
return ContentType.objects.get_for_model(type(self))
class Note(Entry):
text = models.TextField()
class File(Entry):
file_field = models.FileField('File', upload_to='files')
description = models.TextField(blank=True)
这意味着您可以在视图中执行以下操作:
Entry.objects.all().order_by('created')
#get the corresponding child
note = Note.objects.get(entry_ptr_id=parent.pk)
print note.text
有关继承的详细信息,请参阅我的其他post。
为了在模型中保存条目的“真实类型”,我添加了一个real_type字段。这种方法已在this帖子中提出。
在模型中保存real_type
内容类型后,您可以查询所有条目及其详细信息,而无需事先知道您是在处理Notes还是文件。
entries = Entry.objects.all().order_by('created')
for entry in entries:
#get the correct child model
childModel = entry.real_type.model_class()
#get the child
child = childModel.objects.get(pk=entry.pk)
if entry.real_type.model == "Note":
#it s a note object
print entry.text
请注意文档:model_class() returns the Python model class for this type of content.