【问题标题】:Django and DjangoCMS View ManagementDjango 和 DjangoCMS 视图管理
【发布时间】:2020-03-06 00:46:16
【问题描述】:

我试图了解 Django 和 DjangoCMS 是如何管理视图的。

我在项目的urls.py 中有以下内容:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('video/', include('video_uploader.urls')),
    path('user/', include('user_accounts.urls')),
    path('', include('cms.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

也就是说,有几个特定的​​路由,其余的由 DjangoCMS (cms.urls) 处理。

在其中一个应用程序中(对应于上面的/user/ 路径),我有这个:

from django.urls import path

from . import views

app_name = 'user_accounts'
urlpatterns = [
    path('signup', views.user_signup, name='signup'),
]

这条路径的视图如下:

def user_signup(request):
   if request.method == 'POST':
       form = UserCreationForm(request.POST)
       print('Is the form valid?')
       print(form.is_valid())
       if form.is_valid():
           user = form.save()
           login(request, user)
           return redirect('/')
   else:
       form = UserCreationForm()
   return render(request, 'user_accounts/signup.html', {'form': form})

到目前为止,一切都很好。现在我们来看看有趣的部分。

user_accounts/signup.html

{% extends 'base.html' %}

{% block content %}
<div class="container">
    <h2>Sign up</h2>
    <form method="post" novalidate>
    {% csrf_token %}
    {% include 'includes/form.html' %}
    <button type="submit" class="btn btn-primary">Create an account</button>
    </form>
</div>
{% endblock %}

上面的模板扩展了base.html,它是整个项目的基础模板。换句话说,这个注册表单被嵌入到页面的内容块中,以使应用程序具有凝聚力。

在测试注册视图时,我尝试执行以下操作:

class SignUpTest(TestCase):

    def setUp(self):
        url = reverse('user_accounts:signup')
        self.response = self.client.get(url)

    def test_signup_status_code(self):
        self.assertEqual(self.response.status_code, 200)

    def test_signup_url_resolves_signup_view(self):
        view = resolve('/user/signup/')
        print(view)
        print(view.func)
        print(resolve('/video/'))
        print(resolve('/video/').func)
        self.assertIs(view.func, user_signup)

问题是测试失败。它失败了,因为这两个功能不同。

> FAIL: test_signup_url_resolves_signup_view
> (user_accounts.tests.SignUpTest)
> Traceback (most recent call last):   File
> "/home/user-name/sites/project-web/project/user_accounts/tests.py",
> line 20, in test_signup_url_resolves_signup_view
>     self.assertIs(view.func, user_signup) AssertionError: <function details at 0x7f0dc78bf050> is not <function user_signup at
> 0x7f0dc9891200>

它们是什么?

这是我得到的照片。

ResolverMatch(func=cms.views.details, args=(), kwargs={'slug': 'user/signup'}, url_name=pages-details-by-slug, app_names=[], namespaces=[])`
`<function details at 0x7f0dc78bf050>
ResolverMatch(func=video_uploader.views.list_videos, args=(), kwargs={}, url_name=list_videos, app_names=['video_uploader'], namespaces=['video_uploader'])`
`<function list_videos at 0x7f0dc8ecf950>

我正在使用/video/ 路径进行打印,因为该应用程序的设置与相关应用程序几乎相同。主要区别在于前者尚未扩展base.html 模板。看来该视图随后会解析为非 DjangoCMS 视图。

如您所见,访问user/signup/ 时实际使用的视图是一个DjangoCMS 视图。我不理解为什么。有人能告诉我为什么吗?在浏览器中,页面看起来和工作得很好。但是,我希望视图是来自应用程序的视图,而后者只是使用了一些通用模板。

【问题讨论】:

    标签: django django-views django-urls django-cms


    【解决方案1】:

    CMS 网址从这里开始; https://github.com/divio/django-cms/blob/develop/cms/urls.py

    最重要的一点是details 视图; https://github.com/divio/django-cms/blob/develop/cms/views.py#L38

    除了一些实用函数 (here) 之外,CMS 本质上会尝试从提供的 slug(url 路径)中获取页面对象。

    通常在 项目中,您的video_uploaderuser_accounts 等应用程序通过apphooks (docs) 连接到CMS 页面。

    您所展示的是您的应用模板扩展了一个模板,我假设该模板设置为 CMS 模板 base.html。基本模板是否包含 CMS 工具栏?我怀疑您通过扩展模板引起了冲突,因为您说过另一个自定义视图没有扩展同一个模板。

    使用自己的 URL 将您自己的应用程序硬编码到项目中并且不使用 CMS 应用程序钩子并没有什么问题,但如果您这样做了,请保持所有内容隔离,确保模板不会拉入系统的 CMS 端。

    要回答有关应用程序页面的 URL 的问题,您可以在模板中使用一些变量赋值。例如,我有一个无法保证已安装的图库应用程序;

    {% page_url "gallery" as gallery_url %}
    

    这可能不返回任何值,因此可以将其设置为不会执行任何操作的href,或者您可以在条件块中使用它;

    {% if gallery_url %}
        <a href="{{ gallery_url }}">
            Gallery
        </a>
    {% endif %}
    

    【讨论】:

    • 谢谢。这很有帮助。实际上,base.html 是包含 CMS 工具栏的主模板。我对此有点陌生,所以我的想法是我会先构建一个独立的应用程序,然后将其添加到 CMS。
    • 是的,这是一种明智的做法,但是尝试将其转变为 CMS 应用程序,这样做相当简单。它可能会帮助您掌握它的工作方式并避免与“标准 django”方法混淆。
    • 我以前读过那些 apphook 文档。我唯一的困惑是关于包含一个具有多个模板和 urlpatterns 的应用程序。例如,如果我的user_accounts 应用程序管理所有注册、登录、密码重置和其他需求,我是否需要以某种方式为每个任务创建一个单独的 DjangoCMS 页面?还是全部从一个页面中获取?
    • @MadPhysicist 您创建 1 个页面作为该应用程序的“入口点”。因此,所有的 URL 都从您创建的页面开始,解析器从 URL 中查找应用程序的视图。
    • 我明白了。谢谢。
    猜你喜欢
    • 2016-06-18
    • 2012-03-02
    • 2013-07-05
    • 2014-06-23
    • 2020-03-24
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多