我将尝试尽可能简化此操作。可以说我有以下几点:
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表来引用所有人。
理想情况下,我希望能够调用Person的 View ,并以自定义方式为每个类类型列出每个特定的详细信息。我想使用自定义的include_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 %}
...
我走了上面用templatetags编写的路线。但是,我不知道确定人的类型的逻辑放在哪里!
我认为最终我希望能够在Person对象上也对此使用通用 View 。
如果有更好的方法可以做到这一点,我欢迎您提出建议,我只是想让它正常工作。
我已经在这里呆了一天多了……真的可以使用推送。
最佳答案
在Person表上查询后,请参见this answer以获取正确的Person类型子对象的有效方法。
完成这些工作后,您应该能够通过使用多态性来消除模板标签中的大多数复杂性。如果要使用不同的模板显示每个人员类型,请将该模板名称设置为模型的类属性,或者甚至仅基于模型名称(使用person._meta.module_name)设置模板名称。这样,一个简单的模板标记就应该能够涵盖所有情况,甚至不知道存在哪些子类的任何详细信息。 编辑不能使用included_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渲染一个Worker,使用retired.html渲染一个Retired,等等。如果未找到该子类型的特定模板,它将使用默认的person.html。
关于带自定义included_tags的Django模型继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/943020/