python.django.correctness.nontext-field-must-set-null-true.nontext-field-must-set-null-true

Community Favorite
profile photo of semgrepsemgrep
Author
10,112
Download Count*

null=True should be set if blank=True is set on non-text fields.

Run Locally

Run in CI

Defintion

rules:
  - id: nontext-field-must-set-null-true
    patterns:
      - pattern-inside: |
          class $M(...):
            ...
      - pattern-not: $F = django.db.models.CharField(...)
      - pattern-not: $F = django.db.models.TextField(...)
      - pattern-not: $F = django.db.models.SlugField(...)
      - pattern-not: $F = django.db.models.EmailField(...)
      - pattern-not: $F = django.db.models.FileField(...)
      - pattern-not: $F = django.db.models.ImageField(...)
      - pattern-not: $F = django.db.models.URLField(...)
      - pattern-not: $F = django.db.models.UUIDField(...)
      - pattern-not: $F = django.db.models.ManyToManyField(...)
      - pattern-not: $F = django.db.models.NullBooleanField(...)
      - pattern-not: $F = django.contrib.gis.db.models.$MODEL(...)
      - pattern-not: $F = phonenumber_field.modelfields.PhoneNumberField(...)
      - pattern-not: $F = ckeditor.fields.RichTextField(...)
      - pattern-not: $F = $X(..., null=True, blank=True, ...)
      - pattern: $F = $X(..., blank=True, ...)
    message: null=True should be set if blank=True is set on non-text fields.
    languages:
      - python
    severity: ERROR
    metadata:
      category: correctness
      references:
        - https://docs.djangoproject.com/en/4.0/ref/models/fields/#null
      technology:
        - django
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]

Examples

nontext-field-must-set-null-true.py

from django.db import models
from ckeditor.fields import RichTextField
from phonenumber_field.modelfields import PhoneNumberField



class FakeModel(models.Model):
    # ok: nontext-field-must-set-null-true
    fieldChar = models.CharField(
        max_length=200,
        blank=True)
    # ok: nontext-field-must-set-null-true
    fieldPhone = PhoneNumberField()
    # ok: nontext-field-must-set-null-true
    fieldText = models.TextField(blank=True)
    # ok: nontext-field-must-set-null-true
    fieldSlug = models.SlugField(blank=True)
    # ok: nontext-field-must-set-null-true
    fieldEmail = models.EmailField(blank=True)
    # ok: nontext-field-must-set-null-true
    fieldFile = models.FileField(blank=True)
    # ok: nontext-field-must-set-null-true
    fieldImage = models.ImageField(blank=True)
    # ok: nontext-field-must-set-null-true
    fieldURL = models.URLField(blank=True)
    # ok: nontext-field-must-set-null-true
    fieldUUID = models.UUIDField(blank=True)
    # ok: nontext-field-must-set-null-true
    fieldManyToMany = models.ManyToManyField("self", blank=True)
    # ok: nontext-field-must-set-null-true
    fieldCKEditorRichtext = RichTextField(blank=True)
    # ruleid: nontext-field-must-set-null-true
    fieldInt = models.IntegerField(
        blank=True,
        max_value=30
    )
    # ok: nontext-field-must-set-null-true
    fieldIntNull = models.IntegerField(
        null=True,
        blank=True,
        max_value=100
    )

def fake(**kwargs):
    pass

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

def scoped():
    from django.contrib.gis.db import models
    class MyModel(models.Model):
        shape = models.PolygonField(dim=3, srid=4326)
        # ok: nontext-field-must-set-null-true
        grouper_id = models.CharField(max_length=50, blank=True)