2

还在学习 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)
4

0 回答 0