Django models migration gets generated after managed set to False
In my django project, the models Form, FormSubmission, CmsEvent are in a postgres database and the models CmsEventOrder, CmsEventPayment are in another postgres database.
When I makemigrations, the migrations is created for all the models, while it should only be created for CmsEventOrder and CmsEventPayment
Now the models CmsEventOrder and CmsEventPayment have a foreign key to the other 3 models. But the other 3 models have managed false, now do I reference them? Is the migrations getting generated because of the foreign keys?
This is my view
class CreateOrderView(APIView):
def post(self, request):
try:
# Extract data from request
amount = int(request.data.get('amount', 0)) * \
100 # Convert to paise
currency = request.data.get('currency', 'INR')
receipt_id = "receipt_id_" + ''.join(random.choices(
string.ascii_letters + string.digits, k=12))
notes = request.data.get('notes', {})
event_id = request.data.get('event_id')
form_submission_id = request.data.get('form_submission_id')
if amount <= 0:
return Response({"error": "Amount must be greater than zero."}, status=status.HTTP_400_BAD_REQUEST)
# Validate event and form submission
event = get_object_or_404(CmsEvent, id=event_id)
form_submission = get_object_or_404(
FormSubmission, id=form_submission_id)
# Initialize Razorpay client
client = get_razorpay_client()
# Create an order
order_data = {
'amount': amount,
'currency': currency,
'receipt': receipt_id,
'notes': notes
}
order = client.order.create(order_data)
# Save order to database
CmsEventOrder.objects.create(
order_id=order['id'],
receipt_id=receipt_id,
# Convert back to original currency
amount=order['amount'] / 100,
amount_due=order['amount_due'] / 100,
currency=order['currency'],
status=order['status'],
notes=notes,
event=event,
form_submission=form_submission
)
return Response(order, status=status.HTTP_201_CREATED)
except Exception as e:
logger.error("Failed to create order", error=str(e))
return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
And this below is my models
class Form(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, help_text="Enter the form title")
submit_button_label = models.CharField(
max_length=255, help_text="Enter the submit button label (e.g., Submit, Register)"
)
confirmation_type = models.CharField(
max_length=10,
choices=ConfirmationType.choices,
help_text="Select the type of confirmation after form submission"
)
confirmation_message = models.JSONField(
blank=True,
null=True,
help_text="Provide a confirmation message in JSON format if confirmation type is 'Message'"
)
redirect_url = models.URLField(
max_length=2048,
blank=True,
null=True,
help_text="Provide a redirect URL if confirmation type is 'Redirect'"
)
updated_at = models.DateTimeField(
auto_now=True, help_text="Timestamp when the form was last updated"
)
created_at = models.DateTimeField(
auto_now_add=True, help_text="Timestamp when the form was created"
)
class Meta:
app_label = "cms"
db_table = "forms"
managed = False
verbose_name = _("Form")
verbose_name_plural = _("Forms")
def __str__(self):
return self.title
class FormSubmission(models.Model):
id = models.AutoField(primary_key=True)
form = models.ForeignKey(
Form,
on_delete=models.CASCADE,
related_name='submissions',
help_text="Reference to the associated form"
)
updated_at = models.DateTimeField(
auto_now=True,
help_text="Timestamp when the submission was last updated"
)
created_at = models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when the submission was created"
)
class Meta:
app_label = "cms"
db_table = "form_submissions"
managed = False
verbose_name = "Form Submission"
verbose_name_plural = "Form Submissions"
def __str__(self):
return f"Submission {self.id} for Form {self.form_id}"
class CmsEvent(models.Model):
id = models.AutoField(primary_key=True)
event_uuid = models.CharField(
max_length=36, unique=True, editable=False, help_text="Read-only UUID for the event"
)
name = models.CharField(
max_length=128, help_text="Enter the name of the event")
description = models.JSONField(
default=dict, help_text="Provide a detailed description of the event")
image = models.ForeignKey(
"Media", on_delete=models.CASCADE, related_name="events", help_text="Select the event image"
)
venue = models.CharField(max_length=255, blank=True,
null=True, help_text="Enter the venue name (optional)")
city = models.CharField(max_length=255, blank=True,
null=True, help_text="Enter the city (optional)")
locality = models.CharField(
max_length=255, blank=True, null=True, help_text="Enter the locality (optional)")
google_maps_link = models.URLField(
validators=[URLValidator()], help_text="Enter the Google Maps link for the event")
google_form_link = models.URLField(
validators=[URLValidator()], help_text="Enter the Google Maps link for the event")
payment_link = models.URLField(
validators=[URLValidator()], help_text="Enter the Google Maps link for the event")
is_online = models.BooleanField(
default=False, help_text="Check this if the event is only an online event.")
is_online_and_offline = models.BooleanField(
default=False, help_text="Check this if an offline event is also streamed online.")
start_date = models.DateTimeField(
help_text="Event start date with time and timezone")
end_date = models.DateTimeField(
blank=True, null=True, help_text="Event end date with time and timezone")
start_time = models.CharField(
max_length=10, blank=True, null=True, help_text="Enter the start time (e.g., HH:MM)")
end_time = models.CharField(
max_length=10, blank=True, null=True, help_text="Enter the end time (e.g., HH:MM)")
deleted = models.BooleanField(
default=False, help_text="Mark this if the event is deleted.")
is_online = models.BooleanField(
default=False, help_text="Check this if the event is an online event.")
location = models.JSONField(
default=dict, help_text="Provide structured location data for the event")
form = models.ForeignKey(
Form, on_delete=models.SET_NULL, blank=True, null=True, related_name="events",
help_text="Select the associated form for the event"
)
price = models.IntegerField(blank=False, null=False,
validators=[MinValueValidator(0)],
help_text="Enter the price of the event"
)
class Meta:
app_label = "cms"
db_table = "events"
managed = False
verbose_name = _("CMS Event")
verbose_name_plural = _("CMS Events")
def __str__(self):
return self.name
class CmsEventOrder(models.Model):
order_id = models.CharField(
max_length=255, unique=True) # Razorpay order ID
receipt_id = models.CharField(max_length=255, null=True, blank=True)
amount = models.DecimalField(max_digits=10, decimal_places=2)
amount_paid = models.DecimalField(
max_digits=10, decimal_places=2, default=0)
amount_due = models.DecimalField(
max_digits=10, decimal_places=2, default=0)
currency = models.CharField(max_length=10, default='INR')
attempts = models.PositiveIntegerField(default=0)
status = models.CharField(max_length=20, choices=[
('created', 'Created'),
('paid', 'Paid'),
('failed', 'Failed')
], default='created')
# Store event data or other notes
notes = models.JSONField(null=True, blank=True)
form = models.ForeignKey(
Form, on_delete=models.SET_NULL, null=True, blank=True, related_name="orders",
help_text="Associated form for the event order"
)
event = models.ForeignKey(
CmsEvent, on_delete=models.CASCADE, related_name="orders",
help_text="Associated event for the order"
)
form_submission = models.ForeignKey(
FormSubmission,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="cms_event_orders",
help_text="Reference to the associated form submission"
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
managed = True
verbose_name = "CMS Event Order"
verbose_name_plural = "CMS Event Orders"
class CmsEventPayment(models.Model):
order = models.ForeignKey(
CmsEventOrder, on_delete=models.CASCADE, related_name='cmseventpayment')
payment_id = models.CharField(
max_length=255, unique=True)
status = models.CharField(max_length=20, choices=[
('created', 'Created'),
('captured', 'Captured'),
('failed', 'Failed')
], default='created')
payment_verified = models.BooleanField(default=False)
paid_at = models.DateTimeField(null=True, blank=True)
form = models.ForeignKey(
Form, on_delete=models.SET_NULL, null=True, blank=True, related_name="payments",
help_text="Associated form for the event payment"
)
event = models.ForeignKey(
CmsEvent, on_delete=models.CASCADE, related_name="payments",
help_text="Associated event for the payment"
)
form_submission = models.ForeignKey(
FormSubmission,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="cms_event_payments",
help_text="Reference to the associated form submission"
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def is_successful(self):
return self.status == 'captured'
class Meta:
managed = True
verbose_name = "CMS Event Payment"
verbose_name_plural = "CMS Event Payments"
And this is my DB router
import structlog
logger = structlog.get_logger("db_router")
class TerrumCMSRouter:
"""
A database router to direct read operations to the 'terrum_cms' database
and prevent any write operations for models in the 'cms' app.
"""
def db_for_read(self, model, **hints):
if model._meta.app_label == "cms":
logger.debug(f"Read operation routed to 'terrum_cms' for model '{model.__name__}'")
return "terrum_cms"
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == "cms":
logger.warning(f"Write operation blocked for model '{model.__name__}' in app 'cms'")
return None
return None
def allow_relation(self, obj1, obj2, **hints):
db_list = {"default", "terrum_cms"}
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return False
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == "cms" and db == "terrum_cms":
logger.warning(f"Migrations disallowed for app 'cms' in database 'terrum_cms'")
return False
return True
Below are the migration files that get generated with the command python3 manage.py makemigrations payments
Migrations file under app/payments
# Generated by Django 5.1.7 on 2025-03-22 18:19
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("cms", "0001_initial"),
]
operations = [
migrations.CreateModel(
name="CmsEventOrder",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("order_id", models.CharField(max_length=255, unique=True)),
("receipt_id", models.CharField(blank=True, max_length=255, null=True)),
("amount", models.DecimalField(decimal_places=2, max_digits=10)),
(
"amount_paid",
models.DecimalField(decimal_places=2, default=0, max_digits=10),
),
(
"amount_due",
models.DecimalField(decimal_places=2, default=0, max_digits=10),
),
("currency", models.CharField(default="INR", max_length=10)),
("attempts", models.PositiveIntegerField(default=0)),
(
"status",
models.CharField(
choices=[
("created", "Created"),
("paid", "Paid"),
("failed", "Failed"),
],
default="created",
max_length=20,
),
),
("notes", models.JSONField(blank=True, null=True)),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"event",
models.ForeignKey(
help_text="Associated event for the order",
on_delete=django.db.models.deletion.CASCADE,
related_name="orders",
to="cms.cmsevent",
),
),
(
"form",
models.ForeignKey(
blank=True,
help_text="Associated form for the event order",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="orders",
to="cms.form",
),
),
(
"form_submission",
models.ForeignKey(
blank=True,
help_text="Reference to the associated form submission",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="cms_event_orders",
to="cms.formsubmission",
),
),
],
options={
"verbose_name": "CMS Event Order",
"verbose_name_plural": "CMS Event Orders",
"managed": True,
},
),
migrations.CreateModel(
name="CmsEventPayment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("payment_id", models.CharField(max_length=255, unique=True)),
(
"status",
models.CharField(
choices=[
("created", "Created"),
("captured", "Captured"),
("failed", "Failed"),
],
default="created",
max_length=20,
),
),
("payment_verified", models.BooleanField(default=False)),
("paid_at", models.DateTimeField(blank=True, null=True)),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"event",
models.ForeignKey(
help_text="Associated event for the payment",
on_delete=django.db.models.deletion.CASCADE,
related_name="payments",
to="cms.cmsevent",
),
),
(
"form",
models.ForeignKey(
blank=True,
help_text="Associated form for the event payment",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="payments",
to="cms.form",
),
),
(
"form_submission",
models.ForeignKey(
blank=True,
help_text="Reference to the associated form submission",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="cms_event_payments",
to="cms.formsubmission",
),
),
(
"order",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="cmseventpayment",
to="payments.cmseventorder",
),
),
],
options={
"verbose_name": "CMS Event Payment",
"verbose_name_plural": "CMS Event Payments",
"managed": True,
},
),
]
I've crossed the character limit, so here is the migration file under app/cms
on pastebin
I could get it if it created migrations for the models CmsEvent, Form, FormSubmission but it even creates for Media, ShoppingCategory, Brand and BrandRelationship
I don't think that this attribute will do what you want.. if you are aiming to not have migrations files of some of your models then you will have to set attribute abstract
to True
in this case it will not create migration files, you can check the official documentation here they are only talking about this model's migration won't migrate but they didn't say it will not generate migration file.
Anyway, check this issue it says excatly the same (you have to set abstract=True in the model Meta class)
And please be more specific about your libraries' versions (although django version appears in the migration files but you have to place it in your question in a more clear way)