Skip to content

Commit d2c0af8

Browse files
Merge pull request #123 from vishalanandl177/codex/fix-issue-121-mysql-migration
Fix profiling migration defaults for large MySQL upgrades
2 parents 86d6667 + c100c37 commit d2c0af8

8 files changed

Lines changed: 51 additions & 9 deletions

File tree

README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# DRF API Logger
22

3-
[![Version](https://img.shields.io/badge/version-1.2.1-blue.svg)](https://github.com/vishalanandl177/DRF-API-Logger)
3+
[![Version](https://img.shields.io/badge/version-1.2.2-blue.svg)](https://github.com/vishalanandl177/DRF-API-Logger)
44
[![Python](https://img.shields.io/badge/python-3.6+-blue.svg)](https://www.python.org)
55
[![Django](https://img.shields.io/badge/django-3.2+-green.svg)](https://djangoproject.com)
66
[![DRF](https://img.shields.io/badge/djangorestframework-3.12+-orange.svg)](https://www.django-rest-framework.org)
@@ -67,6 +67,33 @@ If using database logging, run migrations:
6767
python manage.py migrate
6868
```
6969

70+
> **Upgrade warning for large MySQL/MariaDB tables:** Version 1.2.0+ adds
71+
> profiling-related columns (`profiling_data` and `sql_query_count`) to the
72+
> `drf_api_logs` table. On large MySQL/MariaDB tables, adding columns can take
73+
> locks or require table rebuilds depending on the database version, storage
74+
> engine, row format, and existing table definition. Plan this migration like a
75+
> production schema change.
76+
>
77+
> Before upgrading, inspect the SQL Django will run:
78+
>
79+
> ```bash
80+
> python manage.py sqlmigrate drf_api_logger 0003
81+
> ```
82+
>
83+
> For large MySQL/MariaDB deployments, validate the generated SQL against your
84+
> exact database/version, prefer database-native online DDL where supported, and
85+
> consider manually adding the columns with a safe online schema migration tool
86+
> or database-native online DDL. If the columns are added manually, fake-apply
87+
> the Django migration afterward:
88+
>
89+
> ```bash
90+
> python manage.py migrate drf_api_logger 0003 --fake
91+
> ```
92+
>
93+
> Avoid copying a generic `ALTER TABLE` command without validating it for your
94+
> database. MySQL and MariaDB online DDL behavior differs by version and table
95+
> definition.
96+
7097
## ⚙️ Quick Start
7198
7299
### Database Logging

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
project = 'DRF API Logger'
77
copyright = '2020, Vishal Anand'
88
author = 'Vishal Anand'
9-
release = '1.2.0'
9+
release = '1.2.2'
1010

1111
extensions = [
1212
'sphinx.ext.autodoc',

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
DRF API Logger
22
==============
33

4-
.. image:: https://img.shields.io/badge/version-1.2.0-blue.svg
4+
.. image:: https://img.shields.io/badge/version-1.2.2-blue.svg
55
:alt: Version
66
.. image:: https://static.pepy.tech/personalized-badge/drf-api-logger?period=total&units=none&left_color=black&right_color=orange&left_text=Downloads%20Total
77
:target: http://pepy.tech/project/drf-api-logger

drf_api_logger/migrations/0001_initial.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class Migration(migrations.Migration):
2929
'verbose_name': 'API Log',
3030
'verbose_name_plural': 'API Logs',
3131
'db_table': 'drf_api_logs',
32+
'ordering': ('-added_on',),
3233
},
3334
),
3435
]

drf_api_logger/migrations/0003_apilogsmodel_profiling.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ class Migration(migrations.Migration):
1111
migrations.AddField(
1212
model_name='apilogsmodel',
1313
name='profiling_data',
14-
field=models.TextField(blank=True, default=None, null=True),
14+
field=models.TextField(blank=True, null=True),
1515
),
1616
migrations.AddField(
1717
model_name='apilogsmodel',
1818
name='sql_query_count',
19-
field=models.PositiveIntegerField(blank=True, default=None, null=True),
19+
field=models.PositiveIntegerField(blank=True, null=True),
2020
),
2121
]

drf_api_logger/models.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,10 @@ class APILogsModel(BaseModel):
8080
profiling_data = models.TextField(
8181
null=True,
8282
blank=True,
83-
default=None,
8483
)
8584
sql_query_count = models.PositiveIntegerField(
8685
null=True,
8786
blank=True,
88-
default=None,
8987
)
9088

9189
def __str__(self):

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def get_long_desc():
1111

1212
setuptools.setup(
1313
name="drf-api-logger",
14-
version="1.2.1",
14+
version="1.2.2",
1515
author="Vishal Anand",
1616
author_email="vishalanandl177@gmail.com",
1717
description="An API Logger for your Django Rest Framework project.",

tests/test_models.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from django.test import TestCase, RequestFactory
55
from django.contrib.admin.sites import AdminSite
66
from django.contrib.auth.models import User
7+
from django.db.models.fields import NOT_PROVIDED
78
from django.utils import timezone
89
from django.test.utils import override_settings
910
from unittest.mock import Mock, patch
@@ -152,6 +153,21 @@ def test_model_max_lengths(self):
152153

153154
self.assertEqual(len(log.api), 1024)
154155

156+
def test_profiling_fields_are_nullable_without_model_defaults(self):
157+
"""Profiling fields should allow NULL without adding Python defaults."""
158+
if not database_log_enabled():
159+
self.skipTest("Database logging is not enabled")
160+
161+
profiling_field = self.APILogsModel._meta.get_field('profiling_data')
162+
sql_query_count_field = self.APILogsModel._meta.get_field('sql_query_count')
163+
164+
self.assertTrue(profiling_field.null)
165+
self.assertTrue(profiling_field.blank)
166+
self.assertIs(profiling_field.default, NOT_PROVIDED)
167+
self.assertTrue(sql_query_count_field.null)
168+
self.assertTrue(sql_query_count_field.blank)
169+
self.assertIs(sql_query_count_field.default, NOT_PROVIDED)
170+
155171

156172
@override_settings(DRF_API_LOGGER_DATABASE=True)
157173
class TestAdmin(TestCase):
@@ -311,4 +327,4 @@ def test_admin_slow_api_filter(self):
311327
admin = APILogsAdmin(self.APILogsModel, self.site)
312328

313329
# Check that SlowAPIsFilter is in list_filter
314-
self.assertIn(SlowAPIsFilter, admin.list_filter)
330+
self.assertIn(SlowAPIsFilter, admin.list_filter)

0 commit comments

Comments
 (0)