Best practices for dependent fields in a django model
For database indexing purposes, the email field on a model needs to be stored in reverse. I end up needing access to both the reversed and forward version of the email field. I'm curious as to which of the following methods would be considered best practice.
Method A
Override the save
method on the model. This method denormalizes the database some and doesn't work with the update
method on a queryset. Some need to override forms generated for the model.
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)
Method B
This way has better database normalization. Still allows you to use the update
method on querysets. Screws up forms so that you end up having to override all of the default forms generated for the model.
class Foo(models.Model):
_email = models.CharField(max_length = 320)
@property
def email_forward(self):
if not hasattr(self, 'email_f开发者_JS百科'):
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
Clarification
Any alternative answers need to meet the minimum requirement of having the reversed email stored in the database. This question is however, not so much about finding an answer to this specific problem, but getting feedback on best practices for this sort of scenario where you have two fields which can be computed from one another, but one is required in a frontend context, and the other in a backend context
The Model:
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)
And the Form:
class FooForm(forms.ModelForm):
class Meta:
model = Foo
Not sure what you meant by "Screws up the form", but this model form will only have one field - the email
. I have also added an example of how the models are used:
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')
精彩评论