【问题标题】:Django dynamic url pattern based on model names: how to do it?基于模型名称的 Django 动态 url 模式:怎么做?
【发布时间】:2020-05-18 16:34:48
【问题描述】:

我搜索了一段时间,但还是没有弄清楚。 假设我们有一个 models.py,其中包含 3 个模型 dogscatsbirds。在 url.py 中,我们希望有一行可以与每个模型类型的通用 ListView 和 DetailView 一起使用。我们的 views.py 是动态的,并接受来自 url.py 的模型。

例如:

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'),
]

所以当我们转到 .../animals/dogs 时,它会从 dog 中加载数据,或者当我们转到 .../animals/cats 时,我们会从 cat 表中获取数据,依此类推。 我们如何做到这一点?

附言我有基于通用的工作views.py,所以我不在这里分享它:)

【问题讨论】:

  • 你见过this SO 帖子,它似乎处理了类似的问题吗?
  • 嗨,克里斯,谢谢,我已经看到了,但我已经实现了一个视图,它可以接受任何传递给它的模型。我的问题与 url 配置和从 urls.py views.AnimalList.as_view(model = {dynamically put models here}) 传递模型有关。

标签: python django generics url view


【解决方案1】:

也许这可以满足您使用inspect 模块的需要:

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]

您可能需要填写your_app_name 或在命名空间中找到正确的名称。 此外,您可能希望将更多过滤选项应用于模型搜索 - 只需通过添加 and/or 条件来扩展 lambda。

【讨论】:

  • 相当不错,似乎是我需要的。我会回来反馈。据我了解,它会自动分配成员,并且不需要像 is_class_member(models) 那样为 lambda 分配模型?
  • 是的,准确的。这里唯一的滑点是sys.modules['your_app_name.models']。我以我编写的方式检查了它是否适用于绝对导入,但对于相对导入,您可能需要检查 modules 键以找到适合您的模型文件的键。
  • 完美解决方案!
【解决方案2】:

我将首先创建一个接受请求和动物类型标头的视图函数。该函数将根据标头查找数据,然后渲染模板。像这样的:

# 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)

如果您需要更多详细信息,请告诉我。

【讨论】:

  • 不,丹尼尔。那不是我想要的。如果我们有大量动物,为每一种动物编写 if 语句是不切实际的。我有基于泛型类的动态视图。他们接受来自 urls.py 的模型。我希望能够在 urls.py 中以一种方式编写,所以它在 url 中传递字符串???作为模型的名称。所以当我们访问 .../animals/dogs 时,views.AnimalList.as_view(template_name = 'animals.html', model = ???) ???变成了狗,所以我的 views.py 从狗那里获取数据,当我们使用猫时,它对猫也是如此,依此类推,我们可能需要尽可能多的模型。
  • 抱歉 - 您是否尝试过扩展默认 ListView 类以包含额外参数?
猜你喜欢
  • 2013-11-18
  • 2021-11-10
  • 2014-02-03
  • 2017-07-30
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
相关资源
最近更新 更多