django - plantillas - reversión de url de plantilla escapando argumentos surt
instalar app django (1)
Tengo un problema en el que la inversión de la URL de la plantilla se escapa de los dos puntos y los caracteres entre paréntesis. Quiero que estos caracteres permanezcan sin guardar en el atributo href de la etiqueta de anclaje. Solía comportarse de esta manera cuando estaba en django 1.3, pero actualizando a 1.6, noté que esto no se comporta como yo quiero.
Lo que tengo:
surt = ''http://(gov/''
browse_domain = ''gov''
... in template ...
<a href="{% url ''nomination.views.url_surt'' project.project_slug surt %}">{{ browse_domain }}</a>
Esto produce:
<a href="/nomination/eth2008/surt/http%3A//%28gov/">gov</a>
Como puede ver, los dos puntos :
e izquierda entre paréntesis (
caracteres se están escapando en el atributo url href. No lo quiero).
Lo que quiero:
surt = ''http://(gov/''
browse_domain = ''Gov''
... in template ...
<a href="{% url ''nomination.views.url_surt'' project.project_slug surt %}">{{ browse_domain }}</a>
Esto produce:
<a href="/nomination/eth2008/surt/http://(gov/">gov</a>
¿Alguien sabe cómo evitar que estos personajes se escapen cuando estoy revocando las URL en mi etiqueta de anclaje?
NOTA: la respuesta a continuación es incorrecta. urllib.quote (safe = '':()'') mantendrá esos personajes seguros sin guardar. Algo más está sucediendo en Django para causar este problema y todavía no sé dónde está.
En Django 1.6, cualquier inversión de URL en la plantilla pasará primero a iri_to_uri()
antes de que se represente en HTML. No hay anulación para esto en la llamada de plantilla a la URL inversa {% url %}
como está.
Observe este fragmento de texto en cursiva que detalla el cambio.
Esto es iri_to_uri()
def iri_to_uri(iri):
"""
Convert an Internationalized Resource Identifier (IRI) portion to a URI
portion that is suitable for inclusion in a URL.
This is the algorithm from section 3.1 of RFC 3987. However, since we are
assuming input is either UTF-8 or unicode already, we can simplify things a
little from the full method.
Returns an ASCII string containing the encoded result.
"""
# The list of safe characters here is constructed from the "reserved" and
# "unreserved" characters specified in sections 2.2 and 2.3 of RFC 3986:
# reserved = gen-delims / sub-delims
# gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
# sub-delims = "!" / "$" / "&" / "''" / "(" / ")"
# / "*" / "+" / "," / ";" / "="
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
# Of the unreserved characters, urllib.quote already considers all but
# the ~ safe.
# The % character is also added to the list of safe characters here, as the
# end of section 3.1 of RFC 3987 specifically mentions that % must not be
# converted.
if iri is None:
return iri
return urllib.quote(smart_str(iri), safe="/#%[]=:;$&()+,!?*@''~")
A primera vista, esto podría parecerse a lo siguiente :
(
y )
están a salvo de la codificación hexadecimal escapada porque se pasan como ''seguros'' a urllib.quote()
:
_safe_map = {}
for i, c in zip(xrange(256), str(bytearray(xrange(256)))):
_safe_map[c] = c if (i < 128 and c in always_safe) else ''%{:02X}''.format(i)
_safe_quoters = {}
def quote(s, safe=''/''):
# fastpath
if not s:
if s is None:
raise TypeError(''None object cannot be quoted'')
return s
cachekey = (safe, always_safe)
try:
(quoter, safe) = _safe_quoters[cachekey]
except KeyError:
safe_map = _safe_map.copy()
safe_map.update([(c, c) for c in safe])
quoter = safe_map.__getitem__
safe = always_safe + safe
_safe_quoters[cachekey] = (quoter, safe)
if not s.rstrip(safe):
return s
return ''''.join(map(quoter, s))
Si urllib.quote()
método urllib.quote()
como se muestra arriba, ''seguro'' en realidad significa que esos caracteres serán escapados / citados . Inicialmente, pensé ''seguro'' significa ''seguro de cita''. Me causó una gran confusión. Supongo que en su lugar significan "seguro" como "seguro en términos de secciones 2.2 y 2.3 de RFC-3986". Tal vez un argumento de palabras clave más elaborado sería prudente, pero, de nuevo, hay una abundancia de cosas que encuentro incómodas con respecto a urllib
. ಠ_ಠ
Después de mucha investigación, y debido al hecho de que no queremos modificar los métodos centrales de Django, nuestro equipo decidió hacer alguna url-construcción hacky en la plantilla (los muy amables documentos de Django lo evitan ). No es perfecto, pero funciona para nuestro caso de uso.