繁体   English   中英

Django模型继承w / custom inclusion_tags

[英]Django model inheritance w/ custom inclusion_tags

我会尽可能地尝试简化这个。 可以说我有以下内容:

models.py

class Person(models.Model):
    name = models.CharField(max_length=255)

    def getRealPerson(self):
        # is there a better way to do this?
        ret = None
        try:
            ret = self.worker
        except:
            try:
                ret = self.retired
            except:
                ret = self
        return ret
class Worker(Person):
    salary = models.IntegerField(default=0)

class Retired(Person):
    age = models.IntegerField()

这个例子对我想要的东西并不重要,请跟我一起去。 这样做的目的是让我可以有一个主人员表来引用所有人。

理想情况下,我希望能够调用Person的视图,并以每种类类型的自定义方式列出每个特定的详细信息。 我想使用自定义的inclusion_tag来执行此操作。

people.html

{% load people_extras %}
{% for person in people %}
   {% show_person person %}
{% endfor %}

people_extras.py - templatetags

from django import template

@register.inclusion_tag('worker.html')
def show_worker(person):
    return {'person':person}

@register.inclusion_tag('worker.html')
def show_retired(person):
    return {'person':person}

#How do I write this function and use it as the show_person person tag?
from project.app.models import Worker, Retired
def show_person(person):
    person = person.getRealPerson():
    if isinstance(person, Worker):
        return show_worker # yes, this doesn't work.

我不知道如何让它根据人物类型调用正确的模板。

我无法弄清楚如何使用{%ifequal%}模板完成此操作,如下所示:

{% ifequal person.getRealPerson.__class__.__name__ "Worker" %}
    {% show_worker %}
...

我用模板标签去了上面写的路线。 但是,我不知道在哪里放逻辑来确定人的类型!

我想最终我希望能够在Person对象上使用通用视图。

如果有更好的方法可以做到这一点,我愿意接受建议,我只是想让它发挥作用。

我已经被困在这里超过一天......真的可以使用推动。

查看此答案 ,了解在Person表上查询后获取正确人员类型子对象的有效方法。

一旦你有了这个工作,你应该能够通过使用多态来消除模板标签中的大部分复杂性。 如果要使用不同的模板显示每个人的类型,请将该模板名称设为模型的类属性,或者甚至根据模型名称创建模板名称(使用person._meta.module_name)。 一个简单的模板标签应该能够覆盖所有情况,甚至不知道存在哪些子类的任何细节。 编辑无法使用inclusion_tag装饰器注册此单个标记,因为您需要动态确定模板名称。 但是使用simple_tag装饰器编写很容易:

@register.simple_tag
def show_person(person):
    t = template.loader.select_template(["%s.html" % person._meta.module_name,
                                         "person.html")
    return t.render({'person': person})

这将使用worker.html呈现工作者,使用retired.html呈现退休等。如果找不到子类型的特定模板,则它将回退到默认的person.html。

利用Django的contenttypes框架来识别您的模型类型。

请参阅以下片段: 儿童感知模型继承并在评论中使用Carl Meyer的建议(将作业包装在“ if not self.id: ”中)

我使用了一种方法,我现在很快就一起攻击,做了一个非常相似的工作。 我有许多模型继承自主“基础”模型 - 我可以通过一个独特的代码访问我数据库中的所有内容(我们称之为“转码”)。 为了找出父对象的子对象,我做了这样的事情:

def get_child_types(self):
    return [ c.__name__.lower() for c in self.__subclasses__() ]

def get_child(self):
    for type in self.get_child_types():
        try:
            o = self.__getattribute__(type)
        except:
            pass
        else:
            return o

我知道它很乱,但它工作正常。 我将对象的“类型”存储在父对象模型的非规范化字段中,因此我只需要“找到”它一次 - 这会减少数据库上的命中数和所需的CPU工作量。 然后我只是覆盖save()以在创建时找到对象类型,并将其存储在该字段中。

希望能帮助到你!

将此片段用于getRealPerson()Person模型方法:

def getRealPerson(self):
    from django.db.models.fields.related import OneToOneRel
    from django.core.exceptions import ObjectDoesNotExist
    for related in self._meta.get_all_related_objects():
        rel_opts_name = related.get_accessor_name()
        if isinstance(related.field.rel, OneToOneRel):
            try:
                sub_obj = getattr(self, rel_opts_name)
            except ObjectDoesNotExist:
                pass
            else:
                return sub_obj

它将返回第一个相关对象(Worker或Retired)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM