0

I was searching this for a while and did not figure out anyway. Let's say we have a models.py with 3 models dogs, cats and birds. In url.py we want to have a single line that works with generic ListView and DetailView for each model type. Our views.py is dynamic and accepts models from url.py.

smth for eaxmple:

from django.urls import path
from django.views.generic import TemplateView
from . import views
from . import models
urlpatterns = [
    path('animals/<???>/', views.AnimalList.as_view(template_name = 'animals.html', model = ???), name='lots'),
]

so when we go to .../animals/dogs, it loads data from dogs, or when we go to .../animals/cats we get data from cats table, and so on. How do we do this?

p.s. I have the working views.py based on generic so I am not sharing it here :)

2
  • Have you seen this SO post which seems to deal with a similar question? Commented Feb 2, 2020 at 21:09
  • hi Chris, thanks, I have seen it, but I already implemented a view that accepts any model passed to it. my problem is related to url configuaration and passing models from urls.py views.AnimalList.as_view(model = {dynamically put models here}). Commented Feb 2, 2020 at 21:14

2 Answers 2

1

Perhaps this will work for your needs with using inspect module:

import sys, inspect

from django.db.models import Model
from django.urls import path
from django.views.generic import TemplateView
from . import views
from . import models

# find classes in models.py
is_class_member = lambda member: inspect.isclass(member)
class_members = inspect.getmembers(sys.modules['your_app_name.models'], is_class_member)

urlpatterns = [
path(f'animals/{item[0]}/', views.AnimalList.as_view(template_name = 'animals.html', model = item[1]), name='lots') for item in class_members]

You may need to fill your_app_name or find the proper name in namespace. Also, you may want some more filtering options to be applied to models search - just extend lambda by adding and/or conditions.

Sign up to request clarification or add additional context in comments.

3 Comments

Pretty nice and seems what I need. I will get back with feedback. as I understand, it automatically assigns members and does not require assigning model for lambda like is_class_member(models)?
Yes, exact. The only slippery thing here is sys.modules['your_app_name.models']. I checked it working for absolute import in a way I wrote it, but for relative import you may need to check modules keys to find the proper one for your models file.
perfect solution!
0

I would start by creating a views function that accepts the request and animal type header. The function will look up the data based on the header and then render the template. Something like this:

# urls.py:

urlpatterns = [
    path('animals/<???>/', views.GetAnimalData, name='lots'),
]


# views.py:

def GetAnimalData(request, animal):

    # 1) look up animal data in database:
    if animal == 'Dog':
        animal_data = Dog.objects.get() # specify query set here
    elif animal == 'Cat':
        animal_data = Cat.objects.get()
    elif ...

    # 2) pack data into context:
    context = {
        'name' : animal_data.name,
        'color' : animal_data.color, 
        ...
    }

    # 3) render template with context:
    return render(request, 'animals.html', context=context)

Let me know if you need more details.

2 Comments

nah, Daniel. that is not what I want. if we have large list of animals, writing if statements for each one is not practical. I have dynamic views based on generic class. they accept the model from urls.py. I want to be able to write inside urls.py a way, so it passes the string in the url ??? as the name of the model. so when we visit .../animals/dogs, the views.AnimalList.as_view(template_name = 'animals.html', model = ???) the ??? becomes dogs, so my views.py getd data from dogs, when we go to cats, it does the same for cats, and so on, for as many models as we might want.
My apologies - have you tried extending the default ListView class to include the extra parameter?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.