Django - 在 .filter(...) 或 .all(...) 之后处理对象

发布于 2024-12-15 07:49:45 字数 2105 浏览 4 评论 0原文

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

Still learning Django, so not sure if there's a nice way to do this.

I have a few models with specific attributes (all use Item as base class), and a metadata table (id, language, type, value) used to store any extra attributes that could be potentially associated with instances of any of those models (code below). These models are used with a form / template, simple web-based CRUD.

Right now, I call .save_metadata(...) and .load_metadata(...) explicitly, and use .form_initia(...) to populate the form with metadata that isn't explicitly in the model.

I'm looking for a way to handle this automatically -- basically implementing a model with a variable number of fields, key ones are columns in the model's table, the other ones are rows in the metadata table, and are instance-specific. Is there a way of hooking a method after objects.get(...) or objects.filter(...) etc? I've messed with custom managers and looked into signals, but nothing seems to lead towards an acceptable solution.

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文