Django-Select2: Select2 for Django

Select2

Select2 is an excellent Javascript framework which transforms mundane <select> fields to cool looking and searchable. This is a very handy when there are quite a number of options to select from.

Basic Select2 options field.

Select2 also allows dynamic fetching of options from server via Ajax. Select2’s webpage has a neat demo of this.

Select2 fetching data via Ajax. In the above screenshot it is using RottenTomatoes’ API to get them.

Django-Select2

Django includes basic select widget, which just generates <select><option>...</option>...</select> tags.  Although their ‘looks’ can be improved using basic CSS, but we hit a usability problem when there are too many options to select from. This is where Django-Select2 comes into picture.

Light Components

Django-Select2 includes many widgets suited to various use-cases. Select2Widget and Select2MultipleWidget widgets are suited for scenarios where we have a static list of choices which may not may not be large. They are not meant to be used when the options are too many, say, in thousands. This is because all those options would have to be pre-rendered onto the page and Javascript would be used to search through them. Said that, they are also one the most easiest to use. They are almost drop-in-replacement for Django’s default select widgets, and they look much much better.

Heavy Components

HeavySelect2Widget and HeavySelect2MultipleWidget widgets are suited for scenarios when the number of options are large and need complex queries (from maybe different data sources) to get the options. This dynamic fetching of options undoubtably requires Ajax communication with the server. Django-Select2 includes a helper JS file which is included automatically, so you need not worry about writing any Ajax related JS code. Although on the server side you do need to create a view specifically to respond to the queries. The format of the response is decided by the JS code being used on the client side. The included abstract view – Select2View, will make sure to format the response into the format expected by the helper JS code. Below is a example on how to use it.

#!python
from django.db.models import Q
from django_select2 import Select2View, NO_ERR_RESP
from .models import Employee

class EmployeeSelect2View(Select2View):
    def check_all_permissions(self, request, *args, **kwargs):
        user = request.user if not (user.is_authenticated() and user.has_perms('emp.view_employees')):
            raise PermissionDenied

    def get_results(self, request, term, page, context):
        emps = Employee.objects.filter( Q(first_name__icontains=term) | Q(last_name__icontains=term) | Q(emp_no__icontains=term))
        res = [ (emp.id, "%s %s" % (emp.first_name, emp.last_name),) for emp in emps ]
        return (NO_ERR_RESP, False, res) # Any error response, Has more results, options list

How many such views you will need depends totally on your use-case. From Django-Select2 there is no restriction on their reuse. If you feel that writing these views are too much of a hassle then you have an alternate option – sub-class AutoSelect2Field field. In your sub-classed field you need to override security_check(self, request, *args, **kwargs) and get_results(self, request, term, page, context) methods. When your field will be instantiated for the first time, it will register its own instance with AutoResponseView. When the related field is used in the browser, the queries would be directed to AutoResponseView which will direct it to your ‘auto’ field instance. For ‘auto’ fields to work you must use the following code in your urls.py to register the url for AutoResponseView.

#!python
urlpatterns += patterns("", url(r"^select2/", include("django_select2.urls")), )

Django-Select2 Fields

The following fields are available in Django-Select2.

  • Select2ChoiceField – Uses Select2Widget.
  • Select2MultipleChoiceField – Uses Select2MultipleWidget.
  • HeavySelect2ChoiceField – Uses HeavySelect2Widget.
  • HeavySelect2MultipleChoiceField – Uses HeavySelect2MultipleWidget.
  • ModelSelect2Field – Uses Select2ChoiceField. It additionally requires queryset argument. It similar to Django’s ModelChoiceField.
  • AutoSelect2Field – Uses HeavySelect2ChoiceField. Auto register’s itself with AutoResponseView.
  • AutoModelSelect2Field – Similar to AutoSelect2Field, but like ModelSelect2Field, normalizes values to Django model objects.

Download Django-Select2

You can download it or fork it from https://github.com/applegrew/django-select2. You can also add this to you pip requirement files as:-

-e git+https://github.com/applegrew/django-select2.git#egg=django-select2

Update: Now can simply add django_select2 to your pip requirement. If you want to install it manually then you can simply run:-

pip install django_select2

Update: Now you can install beta version of django_select2 compatible with Python3.

pip install Django-Select2-Py3

Closing Statement

It is recommended that you go through the codes to familiarize yourself with how to efficiently use Django-Select2. The code is not very complex so you should not face much problem in understanding it.

ADF Super Code Snippets

Oracle’s ADF (Application Developer Framework) is J2EE technology stack to rapidly develop enterprise applications. As with all enterprise applications, ADF focuses on data handling and makes it quite easy to present the data to the users in variety of ways. As you will already know that ADF is a blanket term which encompasses many layers of the full tech stack. So ADF is divided into: –
* ADF Faces – Based on Java Server Faces 1.2 specification, this provides the UI of the application. It is built over Apache MyFaces Trinidad 1.2.x. So this is the View layer of ADF stack.
* ADFc – ADF Controller controls the life cycle of a typical ADF application. In fact it is part of ADF Faces. ADF Task Flows too form part of this layer.
* ADFm – ADF Model provides the brick and mortar to bind ADF Faces to the Model layer. In fact ADFm includes the Binding layer. This allows for loose coupling between the View and Model layers.
* ADF BC – ADF Business Components form the Model layer. It forms the data abstraction layer which does quite a lot of heavy lifting for the ADF stack.

The aim of this post is to list out some tips and code snippets which you may undoubtedly need while coding in ADF.

Some Important notes first

1 Clearing the selection on a ADF tree/tree-table/table from bean

First make sure the tree or tree-table or table does not have selectedRowKeys attribute set. Now you will notice that no row will be selected when the tree loads for the first time, but when user makes a selection then tree builds and stores the RowKeySet of the node the user selected. So, now whenever the tree loads and if the last selected row is visible then it will be shown selected. To work around this, we need to manually clear the tree’s selected rowkeyset after the user has made his selection (e.g. When we hide the tree, just before the tree is shown). Use the following code for that:-

RowKeySet rks = getTree().getSelectedRowKeys();
if (rks != null) {
    rks.clear();
}

2 Get the VO bound to an iterator

Sometimes we may need to manually execute an iterator, for this we need to get the handle to the VO instance bound to an iterator.

private ViewObject getVOFromIterator(DCIteratorBinding it) {
    ViewObject vo = null;
    if (it.hasRSI()) {
        return it.getRowSetIterator().getRowSet().getViewObject();
    } else {
        return it.getViewObject();
    }
}

3 Programmatically add partial target

AdfFacesContext.getCurrentInstance().addPartialTarget(targetComponent);

Make sure that targetComponent is not null else we may get NullPointerException.

4 Get query entered by user in Adf quickQuery component

QueryDescriptor qd = queryEvent.getDescriptor();
AttributeCriterion ac = qd.getCurrentCriterion();
String attrLabel = ac.getAttribute().getLabel();
Object attrValue = ac.getValues().get(0);

Note if you try ac.getValues() then it will mention that it has zero elements, even when get(0) returns a value.

5 Building Disclosed RowKeySet for nodes in a tree/tree-table

/**
* Ref: http://www.oracle.com/technetwork/developer-tools/adf/learnmore/61search-in-rendered-trees-177577.pdf
* @param treeBinding
* @param keys
* @return
*/
private RowKeySet buildDiscloseRowKeySet(JUCtrlHierBinding treeBinding, RowKeySet keys) {
    RowKeySetImpl discloseRowKeySet = new RowKeySetImpl();
    Iterator iter = keys.iterator();
    while (iter.hasNext()) {
        List keyPath = (List)iter.next();
        JUCtrlHierNodeBinding node = treeBinding.findNodeByKeyPath(keyPath);
        if (node != null && node.getParent() != null && !node.getParent().getKeyPath().isEmpty()) {
            //store the parent path
            discloseRowKeySet.add(node.getParent().getKeyPath());
            //call method recursively until no parents are found
            RowKeySetImpl parentKeySet = new RowKeySetImpl();
            parentKeySet.add(node.getParent().getKeyPath());
            RowKeySet rks = buildDiscloseRowKeySet(treeBinding, parentKeySet);
            discloseRowKeySet.addAll(rks);
        }
    }
    return discloseRowKeySet;
}

6 Select a node in tree/tree-table

Variant 1

private void selectNode(List<List<?>> pathKeys, org.apache.myfaces.trinidad.component.UIXTree targetComponent) {
    List<Object> lstKeys = new ArrayList<Object>();
    for(int level = 0; level < pathKeys.size(); level++) {
        List<?> keys = pathKeys.get(level);
        Object[] oKeys = new Object[keys.size()];
        for (int index = 0; index < oKeys.length; index++) {
            oKeys[index] = keys.get(index);
        }
        lstKeys.add(new Key(oKeys));
    }
    if(lstKeys.size() == 1) {
        lstKeys = Collections.singletonList(lstKeys.get(0));
    } else {
        lstKeys = Collections.unmodifiableList(lstKeys);
    }
    RowKeySet keyset = new RowKeySetImpl();
    keyset.setCollectionModel((CollectionModel)(targetComponent.getValue()));
    keyset.add(lstKeys);
    targetComponent.setSelectedRowKeys(keyset); //After this targetComponent.setDisclosedRowKeys()
                                                //needs to be called to reveal the node is its parents
                                                //are collapsed.
}

Where pathKeys is of the following form:- Take an example, where we want to select node C, in the following tree.

A [Row from VO1, keys A1]
|--B [Row from VO2, keys B1, B2, B3]
    |--C [Row from VO3, keys C1, C2]

Then pathKeys will be a list like shown below:-

{ {A1}, {B1, B2, B3}, {C1, C2} }

Variant 2 (Maybe this is a better approach, but not tested)

private void selectNode(List<List<?>> pathKeys, org.apache.myfaces.trinidad.component.UIXTree targetComponent) {
    List<Object> lstKeys = new ArrayList<Object>();
    for(int level = 0; level < pathKeys.size(); level++) {
        List<?> keys = pathKeys.get(level);
        Object[] oKeys = new Object[keys.size()];
        for (int index = 0; index < oKeys.length; index++) {
            oKeys[index] = keys.get(index);
        }
        lstKeys.add(new Key(oKeys));
    }
    if(lstKeys.size() == 1) {
        lstKeys = Collections.singletonList(lstKeys.get(0));
    } else {
        lstKeys = Collections.unmodifiableList(lstKeys);
    }
    JUCtrlHierBinding treeBinding = (JUCtrlHierBinding) ((CollectionModel)targetComponent.getValue()).getWrappedData();
    JUCtrlHierNodeBinding nodeBinding = treeBinding.findNodeByKeyPath(lstKeys);
    Key rowKey = nodeBinding.getRowKey();
    JUIteratorBinding iterator = nodeBinding.getIteratorBinding();
    iterator.setCurrentRowWithKey(rowKey.toStringFormat(true));
}

7 Create a flexible query (search box) which allows you to use custom ViewCriteria with ADF quickQuery

Custom Quick Query ADF Component

Custom Quick Query ADF Component

To create search box like the one above.

UI code

<af:quickQuery id="qq1" queryListener="#{pageFlowScope.Bean.invokeSearch}"
    searchDesc="Quick Search" shortDesc="Quick Search" label="Quick Search">
    <af:inputText id="itQq1" value="#{pageFlowScope.Bean.searchKeyword}"
        simple="true" partialTriggers="cb3" shortDesc="Quick Search"/>
    <f:facet name="end">
        <af:commandButton text="Clear" id="cb3" actionListener="#{pageFlowScope.Bean.clearSearch}"/>
    </f:facet>
</af:quickQuery>

  • We have defined our own input box so that Go button and the auto-generated input boxes get disabled if quickQuery doesn’t have any model.
  • Our custom input box allows us to directly read and modify the input box’s content. This is needed by Clear functionality.
  • Input box has simple set to true, so that its label is not displayed.
  • Official quickQuery reference – http://jdevadf.oracle.com/adf-richclient-demo/docs/tagdoc/af_quickQuery.html.

Bean code (in Bean.java)

private String searchKeyword;

public String getSearchKeyword() {
    return searchKeyword;
}

public void setSearchKeyword(String keyword) {
    searchKeyword = keyword;
}

public void invokeHierSearch(QueryEvent queryEvent) {
    if (searchKeyword != null && !searchKeyword.isEmpty()) {
        DCIteratorBinding it = ADFUtil.findIterator("VOIterator");
        ViewObject vo = getVOFromIterator(it);
        vo.applyViewCriteria(vo.getViewCriteriaManager().getViewCriteria("SearchCriteria"));
        vo.setNamedWhereClauseParam("keyword", searchKeyword);
        vo.executeQuery(); //Iterator will be executed after UI is updated.
        searchVisible = true;
    } else {
        searchVisible = false;
    }
    AdfFacesContext.getCurrentInstance().addPartialTarget(...); //Update UI
}

public void clearSearch(ActionEvent e) {
    searchKeyword = null;
    invokeHierSearch(null);
}

private ViewObject getVOFromIterator(DCIteratorBinding it) {
    ViewObject vo = null;
    if (it.hasRSI()) {
        return it.getRowSetIterator().getRowSet().getViewObject();
    } else {
        return it.getViewObject();
    }
}

8 Get reference to Bindings from bean

DCBindingContainer bindings = ((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry());

9 Programmatically execute iterator

DCBindingContainer bindings = ((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry());
bindings.findIteratorBinding("Iterator").executeQuery();

10 Get reference to method binding (operation binding) in bean

Get bindings from 8.

OperationBinding meth = bindings.getOperationBinding("methodBindingId");
Map args = meth.getParamsMap();
args.put(“arg1”, arg1Value);
…
meth.execute();

11 Get reference to pageFlowScope in bean

AdfFacesContext.getCurrentInstance().getPageFlowScope()

This returns a Map which we can use to read or set values.

12 Evaluate random EL value expressions in bean

FacesContext fc = FacesContext.getCurrentInstance();
ELContext elContext = fc.getELContext();
ExpressionFactory ef = fc.getApplication().getExpressionFactory();
ValueExpression exp = ef.createValueExpression(elContext, "#{expression}", ClassOfOutcomeOfExpression.class);
ClassOfOutcomeOfExpression obj = (ClassOfOutcomeOfExpression) exp.getValue(elContext);

ClassOfOutcomeOfExpression can be Object if you don’t care about the outcome. It has too much boilerplate code.

So place the following code in bean.

private <T> T evaluateEL(String el, Class<T> type) {
    FacesContext fc = FacesContext.getCurrentInstance();
    ELContext elContext = fc.getELContext();
    ExpressionFactory ef = fc.getApplication().getExpressionFactory();
    ValueExpression exp = ef.createValueExpression(elContext, el, type);
    return (T) exp.getValue(elContext);
}

13 Evaluate random EL method expressions in bean

FacesContext fc = FacesContext.getCurrentInstance();
ELContext elContext = fc.getELContext();
ExpressionFactory ef = fc.getApplication().getExpressionFactory();
MethodExpression meth = ef.createMethodExpression(elContext, "#{expression}", Outcome.class, new Class[]{Arg1.class, Arg2.class, …});
Outcome obj = (Outcome) meth.invoke(elContext, new Object[]{arg1Obj, arg2Obj, …});

Example: You need to code the below if you override treetable’s selectionListener.

MethodExpression meth = ef.createMethodExpression(elContext, "#{bindings.treeBinding.treeModel.makeCurrent}",
    Object.class, new Class[]{SelectionEvent.class});
meth.invoke(elContext, new Object[]{selectionEvent});

14 Get value from attribute binding in bean

Get bindings from 8.

((oracle.binding.AttributeBinding)bindings.getControlBinding("bindingName")).getInputValue();

15 Get value from list binding in bean

Get bindings from 8.

((JUCtrlListBinding)bindings.getControlBinding("bindingName")) .attributeValue();

16 Implementing custom selection listener

In this use-case we are providing our own selection listener for the TreeTable because we are interested in capturing the selected node’s VO row instance.

public void onTreeSelect(SelectionEvent selectionEvent) {
    //Invoking makeCurrent manually since it will no longer be called as we have provided our own.
    FacesContext fc = FacesContext.getCurrentInstance();
    ELContext elContext = fc.getELContext();
    ExpressionFactory ef = fc.getApplication().getExpressionFactory();
    MethodExpression meth = ef.createMethodExpression(elContext, "#{bindings.treeBinding.treeModel.makeCurrent}",
        Object.class, new Class[]{SelectionEvent.class});
    meth.invoke(elContext, new Object[]{selectionEvent}); //Selection done now getting data from model.
    RichTreeTable myTree = (RichTreeTable) selectionEvent.getSource(); //changed for Serialization
    RowKeySet rowKeys = selectionEvent.getAddedSet();
    if (rowKeys != null) {
        CollectionModel treeModel = (CollectionModel) myTree.getValue();
        JUCtrlHierBinding treeBinding = (JUCtrlHierBinding) treeModel.getWrappedData();
        Iterator selection = rowKeys.iterator();
        while (selection.hasNext()) {
            //Will loop only once since we have allowed single selection.
            List key = (List) selection.next();
            JUCtrlHierNodeBinding nodeBinding = treeBinding.findNodeByKeyPath(key);
            Row row = nodeBinding.getRow(); //Your custom code which will use row.
                                            //row will be the instance of ViewRowImpl
                                            //which backs the currently selected node.
        }
    }
}

17 Get all rows (nodes) of a Tree or TreeTable

In my use-case I wanted to iterate over all the rows in the TreeTable to find if it has any rows with pending changes. This was to prevent the user from carrying out some actions if there were unsaved changes. There are many ways to achieve this, like check if transaction or view port is dirty, but I did not care about the state of various other components on the page which are outside the tree.

public List<Row> getTreeNodes(CollectionModel treeModel) {
    List<Row> rows = new ArrayList<Row>();
    JUCtrlHierBinding treeBinding = (JUCtrlHierBinding) treeModel.getWrappedData();
    Queue<JUCtrlHierNodeBinding> nodeBindings = new LinkedList<JUCtrlHierNodeBinding>();
    nodeBindings.add(treeBinding.getRootNodeBinding());
    while (!nodeBindings.isEmpty()) {
        List<JUCtrlHierNodeBinding> childNodes = nodeBindings.remove().getChildren();
        if (childNodes != null) {
            for (JUCtrlHierNodeBinding _node : childNodes) {
                nodeBindings.add(_node); rows.add(_node.getRow());
            }
        }
    }
    return rows;
}

18 Programmatically loading resource bundle

Recently I had one requirement where I needed to programmatically load a resource bundle from a managed bean and read the translated strings. I could not find any official documentation on this, and the net is rife with many alternatives which did not work for me. Anyway here is my version which is simple and works well for me.

//import java.util.ResourceBundle;
//import oracle.javatools.resourcebundle.BundleFactory;
ResourceBundle myBundle = BundleFactory.getBundle("fully.qualified.class_name.of.the.bundle");
String msg = getMsg(myBundle, "myKey");

Where the method getMsg() is

public String getMsg(ResourceBundle bundle, String key) {
    if (bundle == null) {
        return "";
    }
    try {
        return bundle.getString(key);
    } catch (MissingResourceException ex) { //Log error here. }
    return "";
}

Please make sure that the bundle class is available on the classpath.

Disclaimer: The views expressed on this blog are my own and do not necessarily reflect the views of my employer. This is may or may not be the recommended way. This is provided here merely in the spirit of sharing. You are more than welcome to post a correction or make an addition in the comment section below. I will happily update this post accordingly.

How to Reset the Root Password of MySql in Linux

I am posting this for my future reference. Also it my help passers by.

If you are using CentOS 6 (maybe others too). To reset the root password use the following steps:-

  1. sudo service mysqld stop
  2. sudo service mysqld startsos
  3. mysql -u root
  4. Now you will be at mysql prompt. Here type:-
    1. UPDATE mysql.user SET Password=PASSWORD(‘NewPassHere’) WHERE User=’root’;
    2. FLUSH PRIVILEGES;
    3. quit;
  5. sudo service mysqld restart