【问题标题】:Django model - set default charfield in lowercaseDjango 模型 - 以小写形式设置默认字符域
【发布时间】:2016-03-31 10:22:40
【问题描述】:

如何设置小写的默认字符域? 这是我的模型:

class User(models.Model):
    username = models.CharField(max_length=100, unique=True)
    password = models.CharField(max_length=64)
    name = models.CharField(max_length=200)
    phone = models.CharField(max_length=20)
    email = models.CharField(max_length=200)

    def __init__(self, *args, **kwargs):
        self.username = self.username.lower()

我尝试了__init__,但它不起作用。每次保存新记录时,我都想将用户名设为小写。谢谢。

【问题讨论】:

标签: django django-models


【解决方案1】:

虽然覆盖save() 方法是一个有效的解决方案。我发现通过覆盖get_prep_value() 方法在Field 级别而不是Model 级别上处理这个问题很有用。

这样,如果您想在不同的模型中重用此字段,您可以采用相同的一致策略。此外,该逻辑与保存方法是分开的,您可能还希望出于不同目的对其进行覆盖。

对于这种情况,您可以这样做:

class NameField(models.CharField):
    def __init__(self, *args, **kwargs):
        super(NameField, self).__init__(*args, **kwargs)

    def get_prep_value(self, value):
        return str(value).lower()

class User(models.Model):
    username = models.CharField(max_length=100, unique=True)
    password = models.CharField(max_length=64)
    name = NameField(max_length=200)
    phone = models.CharField(max_length=20)
    email = models.CharField(max_length=200)

【讨论】:

  • 小错字。 SnpField 应该是 NameField。谢谢你的这个方法。我很欣赏可重复使用的能力。
  • 这个解决方案非常好。我在 SlugField 中添加了 unique=True 并在 save() 中降低了它,但是如果传递了相同的值但不是小写,我得到了 IntegrityError。您的解决方案帮助我克服了它。谢谢
  • +1,此get_prep_value 方法也用于访问数据库,例如我创建了一个 UUID 字段,删除所有“-”符号并使用大写,然后我创建了一个对象并尝试从数据库中获取它:Unit.objects.get(uuid="dc048edf-a08c41c9-b8a2-10e9-7b8752a8") -> <Unit: Unit object (DC048EDFA08C41C9B8A210E97B8752A8)>
  • 出于好奇。在创建NameField 时,get_prep_value 是最好覆盖的函数吗?在 wiesion 的另一个答案中,他使用了to_python 而不是get_prep_value。对此有什么想法吗? stackoverflow.com/a/50895814/8702081
  • @Valachio 根据this answer,“get_prep_value() 只影响保存到数据库的内容,而不影响 Python 对象的内部值”
【解决方案2】:

只需在保存方法中执行此操作即可。即覆盖Model类的save方法。

def save(self, *args, **kwargs):
    self.username = self.username.lower()
    return super(User, self).save(*args, **kwargs)

【讨论】:

  • 重要的是要指出这仅在您的模型更新通过保存时才有帮助。如果您编写在查询集上执行 .update() 的代码,则无需进行保存,因此您的数据库字段中仍可能以大写字母结尾。
  • @aggieNick02 对于这种情况,pre_save 信号会有所帮助。
  • 不,它没有。最近对该答案的编辑应该被恢复,因为它不正确。来自 django 文档:“请注意,update() 方法直接转换为 SQL 语句。它是直接更新的批量操作。它不会在模型上运行任何 save() 方法,也不会发出 pre_save 或post_save 信号”(来源:docs.djangoproject.com/en/dev/topics/db/queries/…
  • 不要覆盖save,它会破坏其他Django方法,例如get_or_create
  • 我发现这个解决方案在您制作新记录时效果很好。但是当您更新现有记录时它不起作用。有谁知道为什么?
【解决方案3】:

信号也有效

from django.db.models.signals import pre_save

@receiver(pre_save, sender=YourModel)
def to_lower(sender, instance=None, **kwargs):
    instance.text = instance.text.lower() if  \
        isinstance(instance.text, str) else ''

【讨论】:

    【解决方案4】:
    def save(self, force_insert=False, force_update=False):
            self.YourFildName = self.YourFildName.upper()
            super(YourFomrName, self).save(force_insert, force_update)
    

    【讨论】:

      猜你喜欢
      • 2016-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-27
      相关资源
      最近更新 更多