Şablon kodu içindeki bir değişkenin değeri nasıl ayarlanır?


216

Diyelim ki bir şablonum var

<html>
<div>Hello {{name}}!</div>
</html>

Test ederken, bu şablonu çağıran python koduna dokunmadan değişkenin değerini tanımlamak yararlı olacaktır. Yani böyle bir şey arıyorum

{% set name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>

Django'da böyle bir şey var mı?

Yanıtlar:


327

withŞablon etiketini kullanabilirsiniz .

{% with name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>
{% endwith %}

35
ancak ile değişkenin değerini değiştirebilir misiniz?
David 天宇 Wong

2
Görünüşe göre bir cümle ile bir konteyner (liste ve tuple denedim) ilan
edemezsiniz

Bir liste bildirmeniz gerekiyorsa, make_list kullanın. docs.djangoproject.com/tr/1.9/ref/templates/builtins/#make-list
MrValdez

3
Jinja neden {% set myvar = value%} olduğunu neden django'da çalışmıyor?
holms

3
@holms Çünkü Django Jinja kullanmıyor :-) docs.djangoproject.com/en/1.7/topics/templates
elimisteve

50

Bir şablon etiketi oluşturun:

Uygulamanın bir içermelidir templatetagsile aynı seviyede, dizin models.py, views.pybu zaten mevcut değilse, vb oluşturun - unutma__init__.py dizin bir Python paketi olarak kabul edilir sağlamak için dosyayı.

Aşağıdaki kodla templatetags dizininin define_action.pyiçinde bir dosya oluşturun :

from django import template
register = template.Library()

@register.simple_tag
def define(val=None):
  return val

Not: Geliştirme sunucusu otomatik olarak yeniden başlamaz. templatetagsModülü ekledikten sonra , etiketleri veya filtreleri şablonlarda kullanabilmek için sunucunuzu yeniden başlatmanız gerekir.


Ardından şablonunuzda bağlama aşağıdaki gibi değerler atayabilirsiniz:

{% load define_action %}
{% if item %}

   {% define "Edit" as action %}

{% else %}

   {% define "Create" as action %}

{% endif %}


Would you like to {{action}} this item?

2
benim durumumda döngü sonra bu eski değeri döndürür :(
holms

7
En son sürümde, atama_tag yerine simple_tag kullanabileceğiniz anlaşılıyor (ve benim için çalıştı).
Katharine Osborne

Bu çözümle ilgili aldığım sorun, değerleri geçersiz kılamamanız.
Jakub Jabłoński

yalnızca bir değer yerine bir liste ayarlamak için bu tekniği kullanmak istiyorsanız, şunu kontrol edin: stackoverflow.com/a/34407158/2193235
msb

değişkeni bir tamsayı olarak ayarlıyorsanız ve artırmak istiyorsanız (örneğin) add: kullanmanız gerekir {% define counter|add:1 as counter %}. Benzer şekilde diğer işlemler için.
msb

35

Her şeyi "ile" bloğuna koymanızı gerektirmeyen alternatif bir yol, bağlama yeni bir değişken ekleyen özel bir etiket oluşturmaktır. De olduğu gibi:

class SetVarNode(template.Node):
    def __init__(self, new_val, var_name):
        self.new_val = new_val
        self.var_name = var_name
    def render(self, context):
        context[self.var_name] = self.new_val
        return ''

import re
@register.tag
def setvar(parser,token):
    # This version uses a regular expression to parse tag contents.
    try:
        # Splitting by None == splitting by spaces.
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
    m = re.search(r'(.*?) as (\w+)', arg)
    if not m:
        raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
    new_val, var_name = m.groups()
    if not (new_val[0] == new_val[-1] and new_val[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
    return SetVarNode(new_val[1:-1], var_name)

Bu, şablonunuza böyle bir şey yazmanıza olanak tanır:

{% setvar "a string" as new_template_var %}

Bunların çoğunun buradan alındığını unutmayın


Bağlamda bulunan diğer değişkenlere değişken atamaya ne dersiniz? Ve farklı bir notta: şablonların, zaten var olup olmadıklarını kontrol etmeden keyfi olarak bağlam değişkenleri atamasına izin vermenin güvenlik sonuçları olabilir. Kanımca daha mantıklı bir yaklaşım, değişkenin içeriğini atamaya çalışmadan önce kontrol etmek olacaktır:
11'te soze

context.get (self.var_name) ise: zam SuspiciousOperation ( "bağlamında zaten mevcut şablondan atama değişkeni girişimi")
Soze

27

John'un tarif ettiği gibi hileler var; ancak, Django'nun tasarım gereği şablon dili bir değişken ayarlamayı desteklemez ( şablonlar için Django belgelerindeki "Felsefe" kutusuna bakın ).
Bu nedenle, herhangi bir değişkeni değiştirmek için önerilen yol olan Python kodunu dokunmadan yoluyla.


7
İşaretçi için teşekkürler. Bir tasarımcının perspektifinden bakıldığında, bir sayfanın tasarımını yaparken çeşitli durumlarını test etmek için bir değişkeni hızlı bir şekilde ayarlamak bazen daha kolaydır. Bu uygulamanın çalışan bir kodda kullanılmasını önermez.
Alexis

2
"with" etiketi django1.0'da kabul edilir. Sonunda felsefelerini değiştiriyorlar gibi görünüyor :).
Evgeny

2
Gerçekler olarak, "with" etiketi yalnızca takma adlar içindir. Bunun performans (ve okunabilirlik üzerinde) üzerinde büyük bir etkisi olabilir, ancak geleneksel programlama terimlerinde gerçekten bir değişken oluşturmuyor.
soymak

12

Bunun için en iyi çözüm bir özel yazmaktır assignment_tag. Bu çözüm bir withetiket kullanmaktan daha temizdir, çünkü mantık ve stil arasında çok net bir ayrım sağlar.

Bir şablon etiketi dosyası oluşturarak başlayın (örn. appname/templatetags/hello_world.py):

from django import template

register = template.Library()

@register.assignment_tag
def get_addressee():
    return "World"

Artık get_addresseeşablonlarınızda şablon etiketini kullanabilirsiniz :

{% load hello_world %}

{% get_addressee as addressee %}

<html>
    <body>
        <h1>hello {{addressee}}</h1>
    </body>
</html>

3
Daha yeni Django sürümlerini kullanan kişiler için buna simple_tag adı verilir! Neden "register .." kodunuzda tanınmadığını bulmak için zaman kazanın ...
kaya

11

Belki de defaultşablon filtresi 2009'da bir seçenek değildi ...

<html>
<div>Hello {{name|default:"World"}}!</div>
</html>

Aradığımın bu olduğunu söylemeliyim! Aynı zamanda kullanılabilen edilebilir ile : {% with state=form.state.value|default:other_context_variable %}yerine other_context_variablebiz de herhangi kullanabilirsiniz 'string_value'yanı
Saurav Kumar

Ama yazdıracak ve daha sonra kullanmak için kaydetmem gerekiyor
holms

4

Bu genel olarak iyi bir fikir değil. Python'daki tüm mantığı yapın ve verileri görüntülemek için şablona aktarın. Tasarım üzerinde çalışanların mantık konusunda endişelenmek yerine tasarıma odaklanmalarını sağlamak için şablon mümkün olduğunca basit olmalıdır.

Bir örnek vermek gerekirse, bir şablon içinde türetilmiş bazı bilgilere ihtiyacınız varsa, bunu python kodundaki bir değişkene almak ve ardından şablona iletmek daha iyidir.


3

With ifadesini kullanın .

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

Bu cevabın ilk paragrafındaki kodu ima edemem . Belki şablon dili eski biçimi kullanımdan kaldırmıştı.


2

Şablonunuzda şunları yapabilirsiniz:

{% jump_link as name %}
{% for obj in name %}
    <div>{{obj.helo}} - {{obj.how}}</div>
{% endfor %}

Şablon etiketlerinize şöyle bir etiket ekleyebilirsiniz:

@register.assignment_tag
def jump_link():
    listArr = []
    for i in range(5):
        listArr.append({"helo" : i,"how" : i})
    return listArr
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.