Home > database >  Django Template: Dynamic template variable inside another variable
Django Template: Dynamic template variable inside another variable

Time:06-12

I hope this makes sense... I am building a crypto asset list page (easy); however, in the {% for %} loop I would like to include a variable inside a variable. Showing the code will make more sense:

Tempalte.html

{% for crypto_asset in objects__list_cryptoAssets %}
   <tr role="row" >
      <td role="cell">{{ api_external_prices.bitcoin.usd }}</td>
   </tr>
{% endfor %}

So the {% for %} loop grabs all the crypto assets and then I can use Django template {{ asset_class.slug }} to grab all slugs... nothing exceptional here. This variable {{ api_external_prices.bitcoin.usd }} grabs external USD prices for Bitcoin, {{ api_external_prices.bitcoin.eur }} prices in EUR, and so forth... nothing exceptional here either.

Here is where the question comes :: the idea would be to have something like {{ api_external_prices.{{ asset_class.slug }}.usd }}... so each crypto would have its own price FX fetched correctly. Is it possible to have a variable inside a variable?

CodePudding user response:

They are several ways you can implement this:

Template filters

You can create a template filter api_external_prices that takes asset_class and the crypto type as parameters and returns the value.

The syntax would be something link this, where api_external_prices is the name of the template filter:

{{ asset_class|api_external_prices:"usd" }}

See here for more info about this feature: https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/#writing-custom-template-filters

Methods

Another approach would be to have api_external_prices as method on your asset_class object, which returns an object that has a usd property. api_external_prices here can just be a wrapper that calls a central module/function, but this would make it much easier to use it in templates.

{{ asset_class.api_external_prices.usd }}

The first approach is similar to what you are asking, but personally I would prefer to use the 2nd approach, because it saves you from introducing as template filter.

CodePudding user response:

I hope this helps on how you could implement Method 2 from your above answer.

Views.py

@login_required(login_url='xxx', redirect_field_name = '')
@require_http_methods(["GET", "POST"])
def view_cryptoAsset_list(request, *args, **kwargs):
    template_name = 'xxx'

    if request.user.is_authenticated and request.user.allow_private_access and request.user.is_superuser:
        if request.method == 'GET':
            context = {}
            objects__list_cryptoAssets = CryptoAsset.objects.all()
            objects__list_foreignExchange = ForeignExchange.objects.all()
            context = get_crypto_asset_list(objects__list_cryptoAssets, context)
            context = get_real_time_prices(objects__list_cryptoAssets, objects__list_foreignExchange, context)
            return render(request, template_name, context)
        else:
            return HttpResponseRedirect(reverse('page__error_404'))
    else:
        return HttpResponseRedirect(reverse('page__home'))

Utils.py

def get_crypto_asset_list(objects__list_cryptoAssets, context):
    if objects__list_cryptoAssets.count() > 0:
        extra_context = {   'xxx': xxx,
                            'xxx': xxx,
                            'xxx': xxx,
                            'xxx': xxx}
    else:
        extra_context = {   'xxx': xxx,
                            'xxx': xxx,
                            'xxx': xxx}
    context.update(extra_context)
    return context

def get_real_time_prices(objects__list_cryptoAssets, objects__list_foreignExchange, context):
    raw_crypto = objects__list_cryptoAssets.values('slug_name')
    dict_crypto = []
    for value in raw_crypto.values():
        raw_slugs = value.get('slug_name')
        dict_crypto.append(raw_slugs)
    stringCrypto = ",".join(dict_crypto)

    raw_foreign_exchange = objects__list_foreignExchange.values('slug')
    dict_fx = []
    for value in raw_foreign_exchange.values():
        raw_slugs = value.get('slug')
        dict_fx.append(raw_slugs)
    stringFX = ",".join(dict_fx)

    url = "xxx"
    response = urllib.request.urlopen(url)
    api_external_prices = json.loads(response.read())

    extra_context = {'api_external_prices': api_external_prices}
    context.update(extra_context)
    return context
  • Related