Whats the logic of importing models as `app_registry.get_model('app_name', 'ModelName')` in a custom migration

◇◆丶佛笑我妖孽 提交于 2019-12-13 04:17:32

问题


I am asking this question because I ran into this django.db.utils.IntegrityError: null value in column “lft” violates not-null constraint when I was using django-hordak which uses MPPT models.

The solution provided is hacky as it violates the common practice but it works.

THE BASICS

In django when writing custom migrations for example when creating baseline data.

def forward_func(apps_registry, schema_editor):
    Model = apps_registry.get_model('app_name', 'ModelName')
    Model.objects.create(**{'field_1': 'field_1', 'field_2': 'field_2')
    # Do whatever you want with my Model 

In my situation django-hordak with the account model. That .objects.create(**data) raises theIntegrityError on the DB as specified above.

Proposed solution

The proposed solution is to import the model directly.

def forward_func(apps_registry, schema_editor):
    # Model = apps_registry.get_model('app_name', 'ModelName')
    # lets forget about importing the standard way because it will raise integrity error.

    from app_name.models import ModelName as Model
    # Now we can proceed to deal with our model without Integrity Error.
    Model.objects.create(**data)

This leaves me scared of possible undesirable side effects of importing models directly in migrations files.

As there must be very good reasons why the model is not imported that way in the migration files.

I am not looking for the reason why MPTT models fail when imported the standard way as that question has an answer here. . I want to understand particularly the logic behind importing models using app_registry.get_model in migration files.


回答1:


that is a very good question, as there is in deed a very big difference.

If you import a model, you will get whatever is currently defined in your model code. But what happens if you want to remove a model? How do you make sure your migration will still work?

That's why there is apps.get_model. It will give you a "virtual" Model based on state defined by the previous migrations. Note that this is not the same as the Model in your code. It does not have any of the custom functions and behaviors you implemented unless they are part of the ORM API. In other words mostly fields and meta options like ordering and co.

Please also note that the correct signature is apps not app_registry. It should not be confused with the app registry in django.apps.apps. It has a get_model method too. This one however will return the model in your current code.

I know it can be all a bit confusing at first (and even later). I would suggest following a simple rule. Do not import any of your own code into a migration. Backport behavior into the migration, if you must.

I hope that distinction helps you a bit. Please leave me a comment if you have further questions. I am happy to extend my answer.

Best -Joe



来源:https://stackoverflow.com/questions/59142674/whats-the-logic-of-importing-models-as-app-registry-get-modelapp-name-mode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!