How to refer to model class (name) from html form to views.py with Django?

Question:

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"  class="btn btn-success" 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?

Asked By: Rivered

||

Answers:

from django.conf import settings
from django.apps import apps


def get_all_models():
    model_name_list = []
    installed_apps = settings.INSTALLED_APPS[6:]
    # 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.

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…

Answered By: Rivered