简体   繁体   English

Django - 用 CharField 上的空字符串替换 None - 最佳实践

[英]Django - Replace None by an empty string on the CharField - best practices

I've decided to review my Django App and I found some issues in my models.我决定检查我的 Django 应用程序,发现我的模型存在一些问题。

My issue is related to the CharField blank and null options.我的问题与 CharField 空白和 null 选项有关。

I was reading about best practices in Django and I've just found out that I was doing everything wrong.我正在阅读 Django 中的最佳实践,我刚刚发现我做的一切都是错误的。 Many posts here explain that we should not use blank and null options on CharField at the same time.这里的很多帖子解释说我们不应该同时在 CharField 上使用 blank 和 null 选项。 To follow the rule I deleted the null=True and kept just blank=True为了遵循规则,我删除了 null=True 并只保留 blank=True

Here comes my doubt: I'm populating my DB from a web scrape code.我的疑问来了:我正在从 web 抓取代码填充我的数据库。 Sometimes the CharField options are returned as None from the website and when my code tried to send it to the DB (I am not doing it in Forms) I get the Invalid Format error telling me that I shouldn't use None - because I took of the null=True.有时 CharField 选项从网站返回为 None 并且当我的代码试图将它发送到数据库时(我不是在表单中这样做)我收到无效格式错误告诉我我不应该使用 None - 因为我采取了的 null=True。

I've read some stuff about it and figure out one solution, which I'm presenting here to hear from you, guys/girls.我已经阅读了一些关于它的资料并找到了一个解决方案,我在这里展示它是为了听取你们的意见,伙计们/女孩们。 Is this the best approach?这是最好的方法吗? I feel like Django might have something out of the box for this very common situation.对于这种非常常见的情况,我觉得 Django 可能有一些开箱即用的东西。

class Empresa(models.Model):
    #I've chosen just some fields to keep it simple

    userstelegram = models.ManyToManyField(UserTelegram, blank=True)
    nome = models.CharField(max_length=150, blank=True)
    denominacao_social = models.CharField(max_length=150, blank=True)
    setor_atividade = models.CharField(max_length=150, blank=True)
    categoria_registro = models.CharField(max_length=100, blank=True)
    cnpj = models.CharField(max_length=100, blank=True)
    coberta = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        self.full_clean(
            exclude = [
                'nome',
                'denominacao_social', 
                'setor_atividade',
                'categoria_registro',
                'cnpj',
            ]
        ) # performs regular validation then clean()

        super(Empresa, self).save(*args, **kwargs)

    def clean(self):
        
        self.cnpj = str(self.cnpj or '').strip()
        self.categoria_registro = str(self.categoria_registro or '').strip()
        self.setor_atividade = str(self.setor_atividade or '').strip()
        self.denominacao_social = str(self.denominacao_social or '').strip()
        self.nome = str(self.nome or '').strip()

    def __str__(self):
        return self.nome if self.nome != None else self.denominacao_social

Two extra questions:两个额外的问题:

1 - I'm using self.full_clean() with the exclude param so the validator does not trigger an error on CharField with None. 1 - 我将 self.full_clean() 与 exclude 参数一起使用,因此验证器不会在带有 None 的 CharField 上触发错误。 Is this the correct way?这是正确的方法吗?

2 - Does the full_clean function use strip() on all string fields? 2 - full_clean function 是否在所有字符串字段上使用 strip()? As I'm excluding my CharFields from the full_clean, should I use the strip on the clean function?由于我从 full_clean 中排除了我的 CharFields,我应该在干净的 function 上使用条带吗?

Thank you, folks!谢谢你们,伙计们!

Your workaround doesn't look clean to me, feels too hack-ish and wrong.您的解决方法对我来说看起来不太干净,感觉太过骇人听闻且错误。

I don't know where you read that that it's a bad idea to set null=True and blank=True at the same time.我不知道您在哪里读到同时设置 null=True 和 blank=True 是个坏主意。 I don't think there is a general rule for this and you should proceed from what you're trying to achieve and what will be most convenient for you in your specific situation.我不认为对此有一般规则,您应该从您想要实现的目标以及在您的特定情况下对您最方便的目标着手。 If you don't really care if some of your char fields could be null and some of them could be blank, and your code will handle both cases just fine then perhaps there is no reason to remove null=True setting?如果您真的不关心您的一些字符字段是否可以是 null 而其中一些可以是空白,并且您的代码可以很好地处理这两种情况,那么也许没有理由删除 null=True 设置? Seems like that decision caused you some troubles and made your code less clean.似乎那个决定给你带来了一些麻烦,让你的代码变得不那么干净。

Anyway, clean method is for validating data, not transforming it.无论如何, clean方法用于验证数据,而不是转换数据。 So, if you set validation to forbid null values in your fields why do you then pass null data?因此,如果您将验证设置为禁止字段中的 null 值,那么为什么要传递 null 数据? If you do want to forbid storing null data then the right approach would be to convert null values that your scraper receives to empty strings before you pass it to your model. This will eliminate the need to implement dirty workarounds with validators.如果你确实想禁止存储 null 数据,那么正确的方法是将你的抓取器接收到的 null 值转换为空字符串,然后再将它传递给你的 model。这将消除使用验证器实施肮脏变通方法的需要。

Does the full_clean function use strip() on all string fields? full_clean function 是否在所有字符串字段上使用 strip()?

It doesn't.它没有。 It only performs a validation.它只执行验证。 So if you want to have your stings stripped before you save them to DB then you should manually stip them, otherwise don't.所以如果你想在将它们保存到数据库之前去除你的刺,那么你应该手动stip它们,否则不要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM