I'm new to Airflow and a bit confused with Default Variables. I have custom operator and I want to use ds in file name.
file_name = str(f) + '{{ ds }}' + str(ext)
The actual result I get is file{{ds}}.docx but I expect file2020-01-01.docx
The strings containing curly braces (e.g.: {{ ds }}) are templated values where Airflow renders certain operator attributes through Jinja2 templating, providing details regarding the current run.
This documentation outlines how to use templating in a custom operator: https://airflow.apache.org/docs/stable/howto/custom-operator.html#templating
Related
I'm attempting to use the jinja templating to parse some json found in xcom into a dictionary. Note below that Operator and templated_field are psuedo-code.
def xcom_from_json(xcom):
xcom_loaded = json.loads(xcom)
logging.info(pformat(f'xcom loaded: {xcom_loaded}', indent=3))
return xcom_loaded
PythonOperator(python_callable=some_callable,
op_args=[f'{{{{ (ti.xcom_pull("{task_id}") | xcom_from_json)["data"]["stats"] }}}}'])
The above works, almost. In the some_callable method I get the parsed jinja, but it comes out as a stringified dict instead of a raw dict. This doesn't make sense, because you can see the structure being traversed as a dict in the jinja template. Does jinja stringify everything coming out of a template? If yes, is there a way to not do that?
A rendered jinja template is always going to return a string. What you can do instead is fetch the XCom value from within the python method instead.
def some_callable(task_id, **context):
stats = json.loads(context['ti'].xcom_pull(task_id)['data']['stats'])
PythonOperator(
...
python_callable=some_callable,
op_args=[f'{task_id}'],
provide_context=True)
Note that you must provide context, which gives the python method the same access to values a jinja template has.
After extensive googling, I still havent come up with an effecient way to solve this.
Im creating a website using Django. I have a db which contains time data, more specifically dates. The value for "the present" is set to 3000-01-01 (YYYY-MM-DD) as is common practice for time-querying.
What I want to do is display a string like "Now" or "Present" or any other value instead of the date 3000-01-01. Is there some sort of global override anywhere that I can use? Seems like a waste to hard-code it in every view/template.
Cheers!
Since this is rendering, I would advice against "subclassing" the DateField such that it renders 'now' instead of the original date(..) object: it will make calculations in the model layer more cumbersome.
Probably a good way to deal with this is implementing a template filter [Django-doc], for example we can construct a file:
# app/templatetags/nowdate.py
from django import template
register = template.Library()
PRESENT = date(3000, 1, 1)
#register.filter
def nowdate(value):
if value == PRESENT:
return 'present'
return value
The templatetags directory of the app application, needs to contain an __init__.py file as well (an empty file), and the app of course needs to be part of the INSTALLED_APPS in the settings.py.
Then we can use it in the template like:
<!-- app/templates/app/some_template.html -->
{{ some_model.some_date_field|nowdate }}
Here we thus fetch the some_date_field of the some_model variable (this attribute is thus a date(..) object), and we pass it through the nowdate filter we have constructed such that, if it is 3000-01-01, it is replaced by the 'present' string.
The advantage here is that if we later change our mind about what date the "present" is, we can easily change it in the template filter, furthermore we can easily extend it, for example by adding a 'past', 'future', etc.
For my python application, I am trying to create and populate a list field in a config file created and deployed by Ansible. Right now it just has one list element (phone_number_), in the future it could have more, hence being a list.
In my jinja2 yaml template I have:
FIELD_NAMES: {{field_names}}
And in my variable var yaml file I have:
field_names: ['phone_number_']
The resulting config file deployed to be server has this line produced:
FIELD_NAMES: [u'phone_number_']
I don't want that unicode "u" in there. How can I get rid of it?
There are to_json and to_yaml filters, that may be helpful.
FIELD_NAMES: {{ field_names | to_json }}
Will give you clean JSON list without unicode markers:
FIELD_NAMES: ["phone_number_"]
You have defined a list with one element:
field_names: ['phone_number_']
I see two options:
1) Reference the variable in your jinja2 template as:
FIELD_NAMES: {{field_names[0]}}
2) Define the variable as a string:
field_names: 'phone_number_'
I'm trying to work out the age of a record in my jinja2 with a filter. I created a simple filter in the following way. The date is stored in a mongodb field and its original form should be of the format of the python datetime object. Here is an example of the record:
"date_update": {
"$date": "2016-02-29T11:13:41.730Z"
},
app.jinja_env.filters['record'] = lambda u: record(u)
def record(date_obj):
print(date_obj)
print(type(date_obj))
return (datetime.datetime.today() - date_obj).days
I use the filter in the following way:
{{ myrec.date_update|record }}
If I look at the output, I see the following:
class 'jinja2.runtime.Undefined'
So my question is, how best should I deal with the dates in jinja2 in the correct format.
This looks like an unknown variable name within your template. From all you've posted so far, it is not clear whether you pass a variable myrec to the template renderer in the first place. So for better help, please post a minimal, self-contained example that exhibits the error.
I have a variable, result, that I display in a Django template using:
{{ result }}
If I set result = "fred", it displays fine.
However, if I set result = "fred\xbf" it is not rendered in the web page.
Why is this? How can I get variables with these types of characters to display?
Are you using Python 2.x? Try prefixing your string with u. Try result = u"fred\xbf".
Sometimes templates eat exceptions and in python 2 not everything is unicode by default.