Skip to content

Commit

Permalink
document django str dunder codemod
Browse files Browse the repository at this point in the history
  • Loading branch information
clavedeluna committed Feb 27, 2024
1 parent d282497 commit b1d623f
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/codemodder/scripts/generate_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ class DocMetadata:
importance="Low",
guidance_explained="Manual instantiation of `asyncio.Task` is discouraged. We believe this change is safe and will not cause any issues.",
),
"django-model-without-dunder-str": DocMetadata(
importance="Low",
guidance_explained="This codemod is a great starting point for models with few fields. We encourage you to write custom `__str__` methods that best suit your Django application.",
),
}

METADATA = CORE_METADATA | {
Expand Down
1 change: 0 additions & 1 deletion src/core_codemods/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,3 @@
SonarDjangoJsonResponseType,
],
)
# Import and add Codemod class to registry above.
10 changes: 6 additions & 4 deletions src/core_codemods/django_model_without_dunder_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
class DjangoModelWithoutDunderStrTransformer(
LibcstResultTransformer, NameResolutionMixin
):
change_description = "todoMoved @receiver to the top."
change_description = "Add `__str__` definition to `django` Model class."

def leave_ClassDef(
self, original_node: cst.ClassDef, updated_node: cst.ClassDef
Expand Down Expand Up @@ -76,10 +76,12 @@ def dunder_str_method() -> cst.FunctionDef:
DjangoModelWithoutDunderStr = CoreCodemod(
metadata=Metadata(
name="django-model-without-dunder-str",
summary="TODOEnsure Django @receiver is the first decorator",
review_guidance=ReviewGuidance.MERGE_WITHOUT_REVIEW,
summary="Ensure Django Model Classes Implement A `__str__` Method",
review_guidance=ReviewGuidance.MERGE_AFTER_REVIEW,
references=[
Reference(url="todohttps://docs.djangoproject.com/en/4.1/topics/signals/"),
Reference(
url="https://docs.djangoproject.com/en/5.0/ref/models/instances/#django.db.models.Model.__str__"
),
],
),
transformer=LibcstTransformerPipeline(DjangoModelWithoutDunderStrTransformer),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
This codemod will flip django's `DEBUG` flag to `False` if it's `True` on the `settings.py` file within django's default directory structure.
This codemod will flip Django's `DEBUG` flag to `False` if it's `True` on the `settings.py` file within Django's default directory structure.

Having the debug flag on may result in sensitive information exposure. When an exception occurs while the `DEBUG` flag in on, it will dump metadata of your environment, including the settings module. The attacker can purposefully request a non-existing url to trigger an exception and gather information about your system.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
If you've ever actively developed or debugged a Django application, you may have noticed Django models and their instances can sometimes be hard to read or distinguish one instance from another. Loading models in the interactive Django console or viewing them in the admin interface can be puzzling. This is because Django is trying to display your model objects as a plain strings.

We've written this codemod to make your model objects human-readable. It will automatically detect all of your model's fields and display them as a nice string.

For example, the `Question` model from Django's popular Poll App tutorial will look like this:
```diff
from django.db import models

class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
+
+ def __str__(self):
+ model_name = self.__class__.__name__
+ fields_str = ", ".join([f"{field.name}={getattr(self, field.name)}" for field in self._meta.fields])
+ return f"{model_name}({fields_str})"
```

Without this change, the `Question` objects look like this in the interactive Django shell:
```
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
```
With this codemod's addition of `__str__`, it now looks like:
```
>>> Question.objects.all()
<QuerySet [<Question: Question(id=1, question_text=What's new?, pub_date=2024-02-21 14:28:45.631782+00:00)>]>
```

You'll notice this change works great for models with only a handful of fields. We encourage you to use this codemod's change as a starting point for further customization.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
This codemod will set django's `SESSION_COOKIE_SECURE` flag to `True` if it's `False` or missing on the `settings.py` file within django's default directory structure.
This codemod will set Django's `SESSION_COOKIE_SECURE` flag to `True` if it's `False` or missing on the `settings.py` file within Django's default directory structure.

```diff
+ SESSION_COOKIE_SECURE = True
Expand Down

0 comments on commit b1d623f

Please sign in to comment.