还在学习 Django,所以不确定是否有一个很好的方法来做到这一点。
我有一些具有特定属性的模型(都使用 Item 作为基类)和一个元数据表(id、语言、类型、值),用于存储可能与任何这些模型的实例相关联的任何额外属性(代码以下)。这些模型与表单/模板、简单的基于 Web 的 CRUD 一起使用。
现在,我显式调用 .save_metadata(...) 和 .load_metadata(...) ,并使用 .form_initia(...) 使用模型中未明确显示的元数据填充表单。
我正在寻找一种自动处理这个问题的方法——基本上实现一个具有可变数量字段的模型,关键的是模型表中的列,其他的是元数据表中的行,并且是特定于实例的。有没有办法在 objects.get(...) 或 objects.filter(...) 等之后挂钩方法?我弄乱了自定义管理器并研究了信号,但似乎没有任何东西可以导致可接受的解决方案。
class Item(models.Model):
mdata = ['title'] # metadata associated with item
user = models.ForeignKey(User)
created = models.DateTimeField(auto_now_add = True)
status = models.IntegerField(default=0, choices = ([(0,'Staged'), (1,'Published'),(2,'Archived'), ]))
def set_status(self, s):
self.status = s
self.save()
# stores metadata attributes associated with current item
def save_metadata(self, lang, form):
for mt in self.mdata:
try:
md = Metadata.objects.get(item=self, lang=lang, t=mt)
except Metadata.DoesNotExist:
md = Metadata.objects.create(item=self, lang=lang, t=mt)
md.v=form.cleaned_data[mt]
md.save()
# retrieves metadata attributes associated with current item
def load_metadata(self, lang):
for mt in self.mdata:
self.__dict__[mt] = None
try:
self.__dict__[mt] = Metadata.objects.get(item=self, t=mt, lang=lang).v
except Metadata.DoesNotExist:
md = Metadata.objects.filter(item=self, t=mt)
if len(md) > 0:
self.__dict__[mt] = md[0].v
# provides metadata attributes associated with current item needed to populate a form
def form_initial(self, seed=None):
meta = {}
for mt in self.mdata:
meta[mt] = self.__dict__[mt]
#meta[mt] = 'test'
if seed:
meta = dict(meta.items() + seed.items())
return meta
# used to store various metadata associated with models derived from Item
class Metadata(models.Model):
item = models.ForeignKey(Item)
lang = models.CharField(max_length = 8)
t = models.CharField(max_length = 250)
v = models.CharField(max_length = 2500)