Django и DjangoCMS View Management - PullRequest
       66

Django и DjangoCMS View Management

0 голосов
/ 09 ноября 2019

Я пытаюсь понять, как 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. Я не понимаю почему. Может кто-нибудь сказать мне, почему? В браузере страница выглядит и работает просто отлично. Тем не менее, я ожидал, что это будет представление из приложения, а последнее просто использует несколько общих шаблонов.

1 Ответ

1 голос
/ 12 ноября 2019

URL 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

Наряду с некоторыми утилитными функциями ( здесь ) CMS в основном пытается получить объект страницы из предоставленного slug (пути URL).

Обычно внутри *Проект 1012 * django-cms , такие приложения, как video_uploader и user_accounts, подключаются к страницам CMS через apphooks ( документы ).

Что выпоказано, что шаблон вашего приложения расширяет шаблон, который, как я предполагаю, настроен как шаблон 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 %}
...