0

I am having trouble running the django migrations on a new database because of the get_or_create() function in a form.

form.py

class EmployeeForm(...):
    # Make sure that we have a directory before initializing the form
    default_upload_directory = Directory.objects.get_or_create(name='Employee', parent=None)[0]

This is the important part of a custom form I wrote. It will link the Employee's uploaded files to a default directory. Everything works fine except for the migration. When I run it on a new database it will complain with django.db.utils.OperationalError: no such table: filemanager_directory. It also happens if I use a standard objects.get(..) to access the Directory object.

I am not sure how to solve this. Obviously the table does not exist, yet. On an existing database with the tables already in place everything works fine.

EDIT: The migrations I am trying to run are not related to this app. Furthermore, as a workaround, you can comment out the line, run the migrations and reactivate it... But this is not a neat solution...

Max
  • 43
  • 6

1 Answers1

2

This is, quite simply, not a thing you should do. You shouldn't run any kind of database access in any code that runs at import time, which this does.

There should never be a need to do this in any case. If your goal is to ensure an object exists when the form is instantiated, put it in the __init__ method.

But you should also reflect that ensuring that database objects exist is the job of migrations in the first place. Write a data migration with a RunPython method to do this.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Thanks for the information. However I would rather like to keep it out of__init__. The reason for this is that we want to make it as simple as possible for other developers to maintain a consistent data flow. That is why we created this form. It ensures that every uploaded file (used in multiple apps) gets attached to the right Directory. That is I liked it this way. The other devs can just set the necessary Model as property and move on. Without overriding anything.. Edit: the error also occurres when we use only `get` to get the desired Directory – Max Jun 03 '17 at 21:26
  • I don't understand how any of that addresses my answer. **Don't do db manipulation at import time**; do it on instantiation, or in a migration. – Daniel Roseman Jun 03 '17 at 21:33
  • I do understand that. But I need a straightforward way of assigning a default model object to the form. Overriding `__init__` for this is not ideal, as I explained above. Using `class Meta` does not work aswell. How would you solve this? And also it is not just about creating the object. The issue rises aswell when only getting the object. Hence I cannot create it during migration – Max Jun 04 '17 at 08:49
  • No, you didn't explain why you can't create it in `__init__`. Maybe you'd better show the whole form, do we can understand what you're doing with that object. – Daniel Roseman Jun 04 '17 at 08:58
  • Code is here: https://pastebin.com/bjxvAbED. This form takes a ModelForm as a base and replaces a specific field (which is defined as foreignkey to the File Model which saves files) with a FileField. That way we can upload files (e.g. profile picture) in various apps but keep the files in only one specific app. The base form only saves the foreignKey of the File object. That way we can process every upload in certain ways: default directory, object based permissions, tagging ... However, we want to keep it as simple as possible for the devs. Hence, only 4 properties to override, not `__init__` – Max Jun 04 '17 at 10:01