0

I would like to access and print metadata (attributes and values) served by an ERDDAP server, which is a variety of OPeNDAP, on my Django website.

so I prepared a simple example function called get_conventions to access a metadata field on this public server hosting data and metadata. To get started, I install the required packages:

$ pip install pandas erddapy

and then,

import pandas as pd
from erddapy import ERDDAP

def get_conventions(dataset_id):
    e = ERDDAP(server='https://gliders.ioos.us/erddap/', protocol='tabledap', response='csv')
    url = e.get_info_url(dataset_id, response='csv')
    df = pd.read_csv(url)

    # this replace spaces with underscores in column names
    df.columns = [col_name.replace(' ', '_') for col_name in df.columns]

    conventions = df[df.Attribute_Name == 'Conventions'].Value
    return conventions

Using a Python interpreter, one could call the function like this with this sample dataset id as an argument (amelia-20180501T0000), which is found on the server; the output follows:

>>> get_conventions('amelia-20180501T0000')
6    Unidata Dataset Discovery v1.0, COARDS, CF-1.6
Name: Value, dtype: object
>>>

I would like my website to print on a webpage the output of the above function.

I can print the argument string in a page (model.py, views.py and a related html templates - those being similar to the Django tutorial), but I am unsure how to refer the argument to the function (and expect a return) or how/where to integrate the function in the Django structure.

The argument is stored in a local database which can be referred using models/views/template

But I am unsure how to integrate the part involving the function in Django?

marsisalie
  • 123
  • 1
  • 5

2 Answers2

1

The approach is going to depend on whether the function is going to be used cross-app, in a single app, or is tied to a Django model.

For cross-app functions, I typically create a separate app called core or utils with python files for each set of functionality. For the sake of your example let's call it erddapy.py. In the views.py that your view is in, simply from utils.erddapy import get_conventions and call it in your view passing in the argument. Then return the result as context to the template.

If it's only being used in a single app but not tied to a model you can also create a utils.py file in that app and instead do from .utils import get_conventions in your views.py then call it in your view.

If you've defined a model for the datasets and store the dataset id there it's probably better suited for a model method. That way you can use the queryset API in your view to get the instance then simply call instance.get_conventions(). You wouldn't need an argument for this approach since you could simply get the dataset id from self.dataset_id in the method logic.

# view
id = self.kwargs.get('id')
if id:
    instance = get_object_or_404(MyModel, id=id)
    data = instance.get_conventions()
# return the data as context in an http response

# model method
class MyModel(models.Model):
    # model fields
    
    def get_conventions(self):
        dataset_id = self.dataset_id
        # get the data
    

I guess the underlying question is how are you storing or obtaining the dataset id? If it's in a separate local database you may need to query it to get the dataset id which I would do in a separate function. Then either pass it into the function as an argument or store it in your Django db as a model instance and use the method approach explained above.

wjh18
  • 685
  • 1
  • 6
  • 13
0

I was able to make this work after reading this, by D. Patel.

It involved adding the following to the file named services.py which was placed an app subfolder titled templatetags. This is where the get_conventions custom function reside:

from django import template
...

register = template.Library()


@register.filter
def get_conventions(dataset_id):
...
    return conventions

and in the template, I had to load the services file and add the following to the html template:

{% load services %}
{% block content %}
    <p><strong>Conventions:</strong> {{ station.dataset_id | get_conventions }}</p>
...
{% endblock %}

station.dataset_id being the argument for the get_conventions function paired | with the return value

and it worked as intended. It was quite straightforward.

marsisalie
  • 123
  • 1
  • 5