查看包含详细信息的不同模型实例的列表

时间:2012-09-26 16:59:51

标签: django django-templates django-views

我有一个“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)

1 个答案:

答案 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.