Sunday 19 October 2014

Regex Golf on regex.alf.nu - Part 1

If you haven't already, go here: http://regex.alf.nu/0

The first one needs you to match words with 'foo' in them, so the solution is straightforward.

foo

The second one has all words that end in 'k'. We use `k` followed by the end of line anchor `$`.

k$

Number 3, Ranges requires you to match all words that contain characters from a to f only.

^[a-f]+$

Backrefs is where it gets interesting. We need to match words that repeat a sequence of characters, like allochirally, heavyheaded or barbary.

(\w{3})\w*\1

Here we match any letter thrice in a group, followed by 0 or more letters followed by our first group. The 0 or more is important in cases like barbary where there is no letter between the group and its repetition.

I had to handle an edge case in Abba, but it looks alright otherwise. The level description is suggestive of a simpler solution but I couldn't figure that out.

^(?:[en](?!n)\w+|(?:(\w)(?!\1))+)$

Visual representation from Debuggex helps a lot in case of complicated regular expressions.



The edge case is for effusive and noisefully.

A man, a plan is similar to Backrefs, but you have to match the reverse of the first group. Again, I couldn't find the proper way, if there is one, but the solution is short and works as well.

^(\w)(\w)\w*?\2\1$

Two groups, one letter each, followed by 0 or more letters, followed by the second group and then the first group, eventually reversing the order.

I will get back to Prime in a later post perhaps.

Four is nice. There might be a possibility of nested groups here though, just to make it shorter.

(\w)\w\1\w\1\w\1

Stay tuned for part 2. If I am ever able to solve the rest.

Wednesday 15 October 2014

Overriding forms in Django admin.

First up, find out where your python packages are stored. This will differ from your system packages if you are in a virtualenv.

echo `which python`

You will get a path like this

/some/path/bin/python

Navigate up a couple of directories and find the django package. Then browse to the following directory. Here you will find all the original templates for django admin.

/some/path/lib/python2.7/site-packages/django/contrib/admin/templates/admin/

My use case required overriding change forms for particular models of some applications.

This is the form that you get once an object of a particular model is saved and you need to change some values / fields in that model.

Copy the change_form.html from the directory and paste it in your projects templates folder. The path would depend on which model you are overriding. Suppose you have model Foo in application ABC.

Copy change_form.html to

templates/admin/ABC/foo/change_form.html

(creating directories where needed). This is your projects' templates folder.

Application name reserves the casing but the model name should be converted to lowercase.

Inside this template you can use {{ original }} along with {{ block.super}} to access the particular object of the model whose form you have overridden. A typical override would look like this, removing the unnecessary stuff.


{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}

{% load static %}

{% block extrahead %}{{ block.super }}
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
	<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
	<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
	<script src="{% static "js/custom.js" %}"></script>
{% endblock %}


{% block after_field_sets %}{{ block.super }}
    <!-- override template here -->
{% endblock %}


You can also override inlines. Suppose you are using ModelAdmin and need to override an inline.
You must add an additional attribute named template to the inline, and giving it the path of the form you have overridden.


We maintain the same directory path convention as found in the site-packages/django/.. directory. But this is not necessary, stacked.html can reside anywhere under templates. Copy it under your templates from the same directory that you copied change_form.html from.


class FooInline(admin.StackedInline):
	model = Foo
	fields = (('a'),('b'),('c'),)
	extra = 0
        template = 'admin/ABC/bar/edit_inline/stacked.html'

class BarAdmin(admin.ModelAdmin):
	list_display = ['b', 'a', 'r']
	inlines = [FooInline]

admin.site.register(Bar, BarAdmin)

admin.site.register(Foo)


Extra headers can be added under the extrahead block.


{% block extrahead %}
    <!-- extra css/js resources defined here -->
{% endblock %}


Custom JavaScript can be linked in the extrahead block or you can have it on the page at the end of the template. Note that if you intend on adding some forms, and have input or button with type="submit", it conflicts with the model's form (you should be able to stop event propagation by handling it, I suppose, this remains to be tried).

If you need to process any input separately, have a button tag with an event listener on it.