Django模型中依赖字段的最佳实践

0 投票
1 回答
2448 浏览
提问于 2025-04-17 02:52

为了数据库索引的目的,模型中的邮箱字段需要以反向存储。我需要同时访问邮箱字段的反向和正向版本。我想知道以下哪种方法被认为是最佳实践。

方法A

重写模型中的save方法。这种方法会让数据库有些不规范,并且在使用update方法时会出现问题。有时候还需要重写为模型生成的表单。

class Foo(models.Model):
  email_forward = models.CharField(max_length = 320)
  email_reversed = models.CharField(max_length = 320)

  def save(self, *args, **kwargs):
    self.email_reversed = reversed(self.email_forward)
    super(Foo, self).save(*args, **kwargs) 

方法B

这种方法更符合数据库的规范化。仍然可以在查询集上使用update方法。但会导致表单出现问题,最终需要重写为模型生成的所有默认表单。

class Foo(models.Model):
  _email = models.CharField(max_length = 320)

  @property
  def email_forward(self):
    if not hasattr(self, 'email_f'):
      self.email_f = reversed(self._email)
    return self.email_f

  @email.setter
  def email_forward(self, value):
    self.email_f = value
    self._email = reversed(value)

  @propery
  def email_reversed(self):
    return self._email

说明

任何替代答案都需要满足一个最低要求,即在数据库中存储反向邮箱。这道问题其实并不是要找到这个具体问题的答案,而是想获得关于这种情况的最佳实践反馈。在这种情况下,有两个字段可以相互计算,但一个是在前端需要,另一个是在后端需要。

1 个回答

1

模型:

class Foo(models.Model):
    email = models.CharField(max_length=320)

    def _get_email_reversed(self):
        return self.email[::-1]

    def _set_email_reversed(self, value):
        self.email = value[::-1]

    email_reversed=property(_get_email_reversed, _set_email_reversed)

还有表单:

class FooForm(forms.ModelForm):    
    class Meta:
        model = Foo

我不太明白你说的“搞砸了表单”是什么意思,不过这个模型表单只会有一个字段,就是 email(电子邮件)。我还加了一个例子,展示这些模型是怎么使用的:

def test_foo(self):
    foo = Foo()
    foo.email = 'moc.elpmaxe@liametset'
    self.assertEquals(foo.email_reversed, 'testemail@example.com')

def test_set_foo_reversed(self):
    foo = Foo()
    foo.email_reversed = 'testemail@example.com'
    self.assertEquals(foo.email, 'moc.elpmaxe@liametset') 

撰写回答