I want users to be able to download a Django model which is being displayed in the app. There can be many types of models, therefore I want to generalize my code. Currently I let users download the model in excel by means of the following code in HTML:
<form id="downloadfile" method="post" action="{% url 'download_file' filename='Irrelevant.xlsx'%}">
{% csrf_token %}
<input type="hidden" value="Plant" name="database" />
<input type="submit" name="downloadfile" value="Download Plant">
</form>
My views.py:
# Define function to download excel file using template
from database.models import Plant
def download_file(request, filename=''):
if 'downloadfile' in request.POST:
db_name = request.POST.get('database')
#How to specify Plant database?
response = xlsx_generator(Plant, db_name) #db_name is used to name the .xlsx file and is just a string.
return response
else:
#some other things to do for other post requests
As you can see, I import the Plant model from database.models
, and refer to it manually in the xlsx_generator. What I would like to do is refer to this imported model from the posted form so that I don't have to refer to it manually anymore. e.g.
db_model = request.POST.get('database')
and then response = xlsx_generator(db_model, db_name)
where db_model refers to Plant model. Can this be achieved? And if yes, how?
CodePudding user response:
from django.conf import settings
from django.apps import apps
def get_all_models():
model_name_list = []
installed_apps = settings.INSTALLED_APPS[9:-1]
# just exclude system app that is not installed by you
for app in installed_apps:
app_config = apps.get_app_config(app)
for model in app_config.get_models():
model_dict = dict()
model_dict['name']: model.__name__
model_dict['value']: model.__name__.lower()
model_name_list.append(model_dict)
return model_name_list
It's a kind of dynamic way to get all models from different apps in your Django project.
CodePudding user response:
Thanks to input of @Md.Imam Hossain Roni, I now have an elegant solution to retrieve model of interest from hidden input in HTML form and pass back model information through response.
views.py
from django.apps import apps
from django.conf import settings
from database.utils import xlsx_generator
from django.http import HttpResponse
def get_all_models():
installed_apps = settings.INSTALLED_APPS[6:]
model_dict={}
# just exclude system app that is not installed by you
for app in installed_apps:
app_config = apps.get_app_config(app)
for model in app_config.get_models():
model_dict[model.__name__] = model
return model_dict
# Define function to download excel file using template
def download_file(request, filename=''):
if 'downloadfile' in request.POST:
db_name = request.POST.get('database')
model_name_list=get_all_models()
response = xlsx_generator(model_name_list[db_name], db_name)
return response
For completeness settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
'database',
'project_management',
]
I do wonder though, that if the model base gets very big, if this dictionary has same size of entire sqlite database, and if this will end up being problematic...