I am creating a Django reusable app, which creates some models and performs certain views on those models.
So I make it as a python package and use it in an independent project. At some point, if I want to uninstall this app, it should remove the tables that it had created in the project's database.
Is it possible to make my python package in such a way to remove all of my app's footprint?
Related
I want to implement a module-manager in Django where third-party modules can be installed through the django admin interface (without changing the code-base of the main project). Or it could also be a service that runs on top of django.
These modules should have the same capabilities as a django app. For example, defining models and views, making migrations, and interacting with other apps. Similar to how it works with the plugin-manager of Wordpress.
Is there a good way to do this? (and are there reasons why I should not?)
What is a Django app? According to Django Packages
Small components used to build projects. An app is anything that is installed by placing in settings.INSTALLED_APPS.
Generally speaking, here are the steps to have an app working in Django
Install the app
pip install app
Register the app in one's settings.py
INSTALLED_APPS = [
...
'app',
...
]
In some cases they'll require to sync the database. Such is the case with social-auth-app-django. Here you'd have to do as well
python manage.py migrate
In some other cases they require specific versions of Python, Django, ect, so that'd have to be taken in consideration too. Such is the case with Django REST framework which requires
Python 3.6+
Django 4.1, 4.0, 3.2, 3.1, 3.0
It's possible as well that apps are dependent on certain Python libraries. Then, one would have to install them too.
For a basic version of that, one wants to create a place to have a button to install an app as well as a model to store the app. The model will keeps track of specific variations with BooleanField.
More precisely, since we now know some apps require database sync, the app model will have requires_db_sync = BooleanField(default=False). Then, if that's true, when installing that app one will want to run at least steps 1, 2 and 3.
One will eventually want to do a thorough analysis of the existing apps and understand the different possible variations (dependencies, requiring DB sync, etc).
I work with WordPress too and this was a thought that came to my mind a few years ago. I didn't pursue it because for most apps I still had to go to the code and do various configurations.
To deal with that, WordPress plugins, like WPForms, come with pages where one does that configuration.
Since such Django app configuration pages for configuration don't yet exist, they'd have to be created as well.
Also, would be great to have a trusted agency with standards to validate an app as good to be in that system.
I have a Django app that I would like to package and offer the community through PyPI repository. Its only strong dependance is Django. It also integrates nicely with Django CMS and offers additional integration for Django CMS. I plan to offer this additional functionality only to projects with Django CMS installed. (This is what I call a weak dependency - will install and work without it, but work even bitter with it.) Specifically, some models are only defined if the base model CMSPlugin from Django CMS is installed.
Is there a good/right way to manage migrations, though?
I cannot include migrations of models depending on CMSPlugin in the package since users w/o a Django CMS installations will not be able to run it.
If I omit the migrations depending on CMSPlugin users with Django CMS will create them on first installation. I fear, however, that on every update of the package those migrations will be lost on pip install upgrade when the package is overwritten.
Since these models are not necessarily used in your package it is best to have them in another Django app, which can be a sub-app of your app or perhaps just one of the apps present in your package. If a user has installed CMSPlugin then they can now simply add this extra app of yours to the INSTALLED_APPS list to use it, this also comes with the benefit that your users now have the choice to use it or not.
This way you can also easily adapt your views if this app is installed or not by using the app registries is_installed method [Django docs]:
from django.apps import apps
def some_view(request):
if apps.is_installed('yourpackage.path.to.weak_dependency_subapp'):
# Weak dependency is present
else:
# Weak dependency is absent
Note: You would have to be careful though that you don't import this apps models if it is not installed, otherwise it may give you some error since it would not be loaded.
Edit: To make the sub-app you can either do as you did by cd'ing to the apps directory and python ../manage.py startapp subappname or directly python manage.py startapp subappname <your_app>/subappname (The directory subappname needs to be made first) and then setting it's app config's name attribute to <your_app>.subappname.
I've done some monkeypatching to some third-party apps in my custom Django 1.10 app, and now, when I try to create an initial migration, it also generates migrations for these external apps, but it puts those migrations in my virtualenv's site-packages directory, where they can't be version controlled.
Moreover, the monkeypatching doesn't actually change the schema. I'm just changing the verbose name and help text to be more user-friendly. There are no changes being made to the database, so there's no actual need to generate migrations for them. How do I generate my app's migration without generating them for external apps?
I tried deleting them, and removing them from my app's migration's dependencies list, but then my unittests won't run and I get the error:
django.db.migrations.exceptions.InvalidBasesError: Cannot resolve bases for...
If I create a normal python package (with __init__.py), instead of manage.py startapp won't I still be able to use it like a django app.?
Django app is actually a python package that follows the Django convention. Django-admin startapp is just a helper command to create the files in that convention. If you want to create an app without using startapp, then can create a folder and create __init__.py file and create the necessary files(for views and models). And you should include it in the INSTALLED_APPS. That's all.
Yes, you will be able to use it as a django app. Django is a web framework, hence its main aim is to allow their users to focus on their applications rather than to make them hard-code every single bit of information.
I have core django admin project that when my customers purchase needs to be modified both in configuration and function. Each customer will have their own instance of the project installed on a different server. Currently I am using django apps to separate out the difference in clients and using settings.py to load the correct app for the correct customer.
So my questions:
Is there a industry standard/best practice/framework to customize configuration and functionality in django admin projects and distribute them?
What would be best to do is write your core project on one side, and store it in a repository (version control). Apart from that, write your sub-applications as requirements and store/track them on separate version control.
Then, to keep everything working together and keep it all integrated, what you should do is that for different functionality, write it all in the same app, but add special settings that change the app's behavior. These settings can be stored in an independent settings_local.py that is imported at the end of your settings file, making them installation-independent, and you keep in your settings.py those that are general to all installations.