python.django.correctness.string-field-null-checks.no-null-string-field

profile photo of semgrepsemgrep
Author
6,206
Download Count*

Avoid using null on string-based fields such as CharField and TextField. If a string-based field has null=True, that means it has two possible values for "no data": NULL, and the empty string. In most cases, it's redundant to have two possible values for "no data;" the Django convention is to use the empty string, not NULL.

Run Locally

Run in CI

Defintion

rules:
  - id: no-null-string-field
    patterns:
      - pattern-inside: |
          class $M(...):
            ...
      - pattern-not: $F = django.db.models.CharField(..., null=True, unique=True,
          blank=True, ...)
      - pattern-not: $F = django.db.models.TextField(..., null=True, unique=True,
          blank=True, ...)
      - pattern-either:
          - pattern: $F = django.db.models.CharField(..., null=True, ...)
          - pattern: $F = django.db.models.TextField(..., null=True, ...)
    message: "Avoid using null on string-based fields such as CharField and
      TextField. If a string-based field has null=True, that means it has two
      possible values for \"no data\": NULL, and the empty string. In most
      cases, it's redundant to have two possible values for \"no data;\" the
      Django convention is to use the empty string, not NULL."
    languages:
      - python
    severity: WARNING
    metadata:
      category: correctness
      technology:
        - django
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]

Examples

string-field-null-checks.py

from django.db import models
from django.db.models import Model

class FakeModel(Model):
    #ruleid: no-null-string-field
    fieldOne = models.CharField(
        max_length=200,
        null=True)
    # ruleid: string-field-must-set-null-true
    fieldTwo = models.CharField(
        unique=True,
        blank=True,
        max_length=30
    )
    # ruleid: string-field-must-set-null-true
    fieldAAAAA = models.TextField(
        unique=True,
        blank=True,
        max_length=30
    )
    # ok: string-field-must-set-null-true
    fieldThree = models.CharField(
        unique=True,
        null=True,
        blank=True,
        max_length=100
    )
    # ok: string-field-must-set-null-true
    notText = models.IntegerField(
        max_value=255
    )

def fake(**kwargs):
    pass

def nope():
    # ok: string-field-must-set-null-true
    return fake(unique=True, blank=True)