Використовується {% url ??? %} у шаблонах django


83

Я багато шукав у Google відповіді на те, як використовувати тег 'url' у шаблонах, лише щоб знайти багато відповідей, в яких говориться: 'Ви просто вставляєте його у свій шаблон та спрямовуєте на вигляд, для якого потрібно URL-адресу'. Ну ніякої радості для мене :( Я спробував усі можливі перестановки і вдався до публікації тут як крайній засіб.

Отож воно. Мій urls.py виглядає так:

from django.conf.urls.defaults import *
from login.views import *
from mainapp.views import *
import settings

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Example:
    # (r'^weclaim/', include('weclaim.foo.urls')),
    (r'^login/', login_view),
    (r'^logout/', logout_view),
    ('^$', main_view),

    # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    (r'^admin/', include(admin.site.urls)),
    #(r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root': '/home/arthur/Software/django/weclaim/templates/static'}),
    (r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}),
)

Мій 'views.py' у моєму каталозі 'login' виглядає так:

from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.contrib import auth

def login_view(request):
    if request.method == 'POST':
        uname = request.POST.get('username', '')
        psword = request.POST.get('password', '')
        user = auth.authenticate(username=uname, password=psword)
        # if the user logs in and is active
        if user is not None and user.is_active:
            auth.login(request, user)
            return render_to_response('main/main.html', {}, context_instance=RequestContext(request))
            #return redirect(main_view)
        else:
            return render_to_response('loginpage.html', {'box_width': '402', 'login_failed': '1',}, context_instance=RequestContext(request))
    else:
        return render_to_response('loginpage.html', {'box_width': '400',}, context_instance=RequestContext(request))

def logout_view(request):
    auth.logout(request)
    return render_to_response('loginpage.html', {'box_width': '402', 'logged_out': '1',}, context_instance=RequestContext(request))

і нарешті main.html, на який виглядають точки login_view:

<html>
<body>
test! <a href="{% url logout_view %}">logout</a>
</body>
</html>

То чому я отримую "NoReverseMatch" щоразу?

* (за дещо іншою нотою мені довелося використовувати 'context_instance = RequestContext (request)' в кінці всіх моїх рендерів до відповідей, оскільки інакше він не розпізнавав би {{MEDIA_URL}} у моїх шаблонах, і я не міг посилатися будь-які файли css або js. Я не впевнений, чому це так. Мені це не здається правильним) *


1
Те, що ви говорите про context_instance=RequestContext(request)правильне, це потрібно, щоб надати шаблону доступ до контекстних змінних, що надаються для всіх шаблонів. Це робиться за замовчуванням для всіх загальних подань, але вам потрібно зробити це самостійно у власних.
Marcus Whybrow

Мені здається трохи дивним, тому що ви збираєтесь постійно отримувати доступ до своїх файлів css та js зі своїх шаблонів, щоб зберегти узгодженість на вашому сайті. Тому ви не повинні мати змогу отримати доступ до {{MEDIA_URL}} за замовчуванням?
Роберт Джонстон,

1
Прийнята відповідь тут вже недійсна
Ден Гейл, 02

Додайте нову відповідь, і тоді я прийму це
Роберт Джонстон

Відповіді:


54

Замість того, щоб імпортувати logout_viewфункцію, ви повинні вказати рядок у своєму urls.pyфайлі:

Тож ні (r'^login/', login_view),

але (r'^login/', 'login.views.login_view'),

Це стандартний спосіб робити щось. Тоді ви можете отримати доступ до URL-адреси у своїх шаблонах, використовуючи:

{% url login.views.login_view %}

2
так, однозначно використовуйте рядки. таким чином, ви також можете використовувати префікси, і вам не потрібно імпортувати всі свої функції перегляду у свій URLConf.
Шрі Раґгаван

Я теж спробував це і отримав "Caught NoReverseMatch під час рендерингу: Зворотне значення для" login.views.login_views "з аргументами" () "та аргументами ключового слова" {} "не знайдено." ще раз :(
Роберт Джонстон

Зачекайте ... Подряпайте це! Я зачекав 15 хвилин, спробував ще раз, і це спрацювало (yippeeee !!!). Приємно 1. Наступне питання. Якщо у мене є лише один сайт, який я додав на сторінці адміністратора, як я можу суфіксувати це на {% url ??? %}
Роберт Джонстон

Так, це некро, але тег URL все ще кусає мене в 2015 році. Це допомогло б, якби вони не продовжували змінювати синтаксис:
Дейв

6
Тільки тому, що я прийшов сюди з google, я повинен сказати, що щодо django 1.8+, передача рядків як аргументу подання застаріла і незабаром буде видалена. Ви насправді повинні пройти виклик, як у цій публікації.
user3599803

104

Вибрана відповідь застаріла, і жоден інший не працював у мене (Django 1.6 та [очевидно] відсутність зареєстрованого простору імен.)

Для Django 1.5 та пізніших версій (з документації )

Попередження Не забувайте ставити лапки навколо шляху до функції або назви шаблону!

За допомогою названої URL-адреси ви можете зробити:

(r'^login/', login_view, name='login'),
...
<a href="{% url 'login' %}">logout</a>

Так само просто, якщо подання приймає інший параметр

def login(request, extra_param):
...
<a href="{% url 'login' 'some_string_containing_relevant_data' %}">login</a>

1
так, я знаю. {% load url from future %}На даний момент я використовую версію 1.4. Гарне місце
Роберт Джонстон

5
Це слід вибрати як відповідь. Використання рядків для зворотних відповідних URL-адрес застаріло в нових версіях django.
Сумуду

44

Переконайтеся, що (django 1.5 і пізніші) ви вводите ім'я URL-адреси в лапки, і якщо ваша URL-адреса приймає параметри, вони повинні знаходитися поза лапками (я годинами з'ясовував цю помилку!).

{% url 'namespace:view_name' arg1=value1 arg2=value2 as the_url %}
<a href="{{ the_url }}"> link_name </a>

Я знаю, що це стара відповідь, але це мені справді допомогло. Я використовую django-norel, що є форком Django 1.6, який також повинен страждати від цієї проблеми, оскільки інкапсуляція імені url у лапки виправляла TypeError, яку я отримував.
robobrobro

2
Використання правильної документації теж допомагає, оскільки вони продовжують змінювати синтаксис: {% url app_views.client client.id %}(без лапок) у 1.4, {% url 'app_views.client' client.id %}(з лапками) в 1.5 -1.7 та {% url 'app-views-client' client.id %}(без підкреслення чи крапок, лише тире) у 1.8.
Дейв

О Господи, і я планував незабаром перейти на 1.8.
Богатир

17

urlШаблонний тег буде передати параметр у вигляді рядка , а не в якості опції посилання reverse(). Найпростіший спосіб отримати цю роботу - це додати a nameдо подання:

url(r'^/logout/' , logout_view, name='logout_view')

Я спробував це, але отримав "невірний синтаксис (urls.py, рядок 14)" :(
Роберт Джонстон,

що насправді дивно в цьому, так це те, що він (PyCharm - приємний додаток) не дозволяє мені використовувати> name = 'logout_view' <як вище, не рекомендуючи імпортувати бібліотеку (libxml2mod.name або unicodedata.name або twisted.trial.runner. ім'я)
Роберт Джонстон

Де reverse()визначена функція ?
CodyBugstein 01.03.14

У вашому шаблоні за допомогою {% url 'logout_view'%} django.readthedocs.org/en/latest/intro/tutorial03.html
Хуан Рохас

12

Я стикаюся з тією ж проблемою.

Те, що я знайшов з документації, слід використовувати namedspace.

у вашому випадку {% url login:login_view %}


Зараз просто більше використовую простори імен. Робить URL більш читабельним, і вони насправді щось значать для вас
Роберт Джонстон,

Чи можете ви включити посилання на документацію, будь ласка?
геоїдезичний

1

Судячи з вашого прикладу, чи не повинен бути це {% url myproject.login.views.login_view %}кінець історії? (замінити myprojectна фактичну назву проекту)


Так само, як і у вищезгаданому 'Caught NoReverseMatch під час рендерингу: Зворотне значення для' weclaim.login.views.login_views 'з аргументами' () 'та аргументами ключового слова' {} 'не знайдено.' (Я припускаю, що назва мого проекту збігається з кореневою директорією, у якій зберігається весь мій код)
Роберт Джонстон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.