Feb 3, 2014

Django: adding additional Admin static and writing JS snippets for Django Admin

It often gets that you need it because you invent something that is meant to be displayed for admin. E.g. some nasty form field or something. Here is my recipe to add some additional Django static to your admin.

Rather than writing a widget, that is more proper way here... I was using a widget already (from another package). So I could not use it properly, at least without a ton of overrides and complexity it leads to. SO I've decided to add the JS functionality to override a lack of backend.

First of all we should add the javascript/css like so:
# admin.py
class MyModelAdmin(admin.ModelAdmin):
    # admin additions

    class Media:
        css = {
            "all": ("css/my_style.css",)
        }
        js = ("js/my_script.js",)
This add should list your files, loaded in the admin. So you can access them and see in the Django admin frontend itself. Like so:
Now that your script and style are loaded you could just hack anything you want dynamically. Django admin already has a jQuery attached, so you can do whatever you want with it. But there is a problem. You can not just do $(....... your code. This simply does not work and will get error like this:
(Uncaught TypeError: Property '$' of object [object Object] is not a function)
There is no usual jQuery namespace there. but there is a simple hack.
var $ = django.jQuery;

// your usual jQuery code goes here
// e.g.:
// $(document).ready(function() {
    // $('#admin_big_image').wrap('<div class="mrmen-b">');
// });
Thats all. Yu may improvise. E.g. dynamically create or alter DOM elements and manipulate them. Im my case it was a simple Admin banner overlay into image displayed by 3-d party django plugin.
Imagination is the limit.

External links:
http://stackoverflow.com/questions/4709298/difficulty-with-django-and-jquery-why-is-undefined-in-the-admin-app About what may be wrong with your scripts
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-asset-definitions About whee is this idea taken from in Django docs.

Suggestions? Wrong? Comment here!

Jan 2, 2014

Lightning unofficial cable trick for iOS 7

I have found a hack of how to firs time sync your iphone via unofficial (cheap Chinese) cable.
It may be a hint to you if you are buying an iPhone from a second hand without accessories.

You will need TADAA! Official Apple cable but not for a lightning port. And another Apple device.

The thing is if you connect both your new iPhone or iPad via lightning port and using unofficial cable and ANY of your Apple devices using OFFICIAL Apple cable. It will trust your lightning connected device.

Some magic happens and one device connected with official apple cord makes another device connected via official cord too.

TADAA. Now you can sync at least once... and use Wi-Fi sync later on...

Hopoe it helps you. Comments?

Dec 30, 2013

CentOS Install SSH server and configure for VirtualBox testing

I have had some tasks to configure and install a CentOS distribution for my bug-tracking needs. Hope to help out someone with similar problems and or tasks.

I'll be using a fresh install of a CentOS Minimal 6.5.  And a Mac Book Pro with VirtualBox installed (as my testing environment).

First after install of a clean CentOS you need an SSH server to work in your usual environment. So to connect to a Linux, installed in a VirtualBox you will need basically 2 things:
  • openssh-server install
  • disable firewall
  • VirtualBox Port configuration/Access configuration

OpenSSH server install

To install server you need to run in your VirtualBox Guest system (CentOS VM):
yum -y install openssh-server
And start and add it to auto launch at system startup:
chkconfig sshd on
service sshd start
Also make sure port 22 is opened in your VM. type:
netstat -tulpn | grep :22

Firewall settings

Because it's a VM you can simply disable the firewall. But be sure not to do this at deployment/production server of any kind.

To disable firewall and remove from auto lunch at system startup run:
service iptables stop
chkconfig iptables off

VirtualBOX

To connect your Guest machine to your Host machine (basically up a network between virtual CentOS and your host Mac OS (In my case) you have several options.
I'll stop on a simple one. You may do a Bridged network connection and have your router/whatever assign your VM an IP address inside your network.
You may also select NAT and configure port mappings. But it's fairly more complex rather then this setting and exceeds the scope of this article.

Connect

Now you need to reboot your CentOS or either reboot network inside your VM. As a result, after reboot you should get assigned IP address. You can view it using command:
$ ifconfig
eth0      Link encap:Ethernet  HWaddr XX:XX:XX:XX:XX:XX  
          inet addr:192.168.1.104  Bcast:192.168.1.255  Mask:255.255.255.0
Mine got an IP ending with 104.
And so now you can ssh connect to your VM terminal using something like:
$ ssh root@192.168.1.104
root@192.168.1.104's password: 
Last login: ...
[root@localhost ~]# 
Tadaa! Your system is up and ready for experiments. Just be sure to save your state with VM snapshots ;)

Comments?

Dec 13, 2013

Python Generators explained simply.

I'm often confused by recent obsession of generators in python. I'll try to explain them as simply as possible. Say you have never used iterators but coded in python. BUT I'm sure you have used dictionaries (dict) and have met requirement to iterate through it's keys and/or values. TADA! You have used generators already ;).

So generator is a function in python. Except for it uses a keyword yield in it's code. Thus making it the iterator. So you could call this function in a sequence like you would probably do iterating over a dictionary already. E.g.:
# typical iteration through dictionary key: value set
for key, value in dict.iteritems():
   # do someth

# Usage of your own iterator
for item in iterator_functuon():
   # do something with function generated output
So this function returns an iterator generator like the dict() type has by default. And has a next() function, like usual iterators have.
So in attempt to using human language:
Generators are simple functions converted to iterators.
So when a generator function calls it's magic word yield, the "state" of the generator function is frozen; the values of all variables are saved and the next line of code to be executed is recorded until next() is called again. Once it is, the generator function simply resumes where it left off. If next() is never called again, the state recorded during the yield call is (eventually) discarded.
So. that was the theory. Better to look at example well commented out:
def gen_odd_nums():
 # executed once (first call) usually like __init__() of a generator
    odd_num = 1
    while True:
     # saves context and return from function
        yield odd_num
        odd_num = odd_num + 2

# Typical generator usage
generator_object = gen_odd_nums()  # initialising a generator once
for i in range(5):
 # calls generator_object.__next__()
    print next(generator_object)
Output will be like:
1
3
5
7
9
That's probably all the magic about the generators. Best way to get it is to open your console. NOW! And try to do it yourself.

Comments?

Nov 29, 2013

AJAX form in Django with jQuery.form plugin

Here I will describe an example form using jQuery Form plugin. It will provide a good frontend, while Django serving a simple backend.
I made this AJAX form using unobtrusive javascript. With human language it means the form will function with JavaScript disabled. And so jQuery.form plugin will work as an AJAX speedup addition and not as a major requirement.

Features:
* Works both with JavaScript  and without.
* Uses standard Django ideology/hooks.
* Uses the most known jQuery plugin for forms AJAX handling.

Theory:
Main idea that Django supports both normal and AJAX request in a standard view. And has a handy request.is_ajax() request method. It returns True/False depending on if request search has HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'. jQuery.form plugin sure does have that.

Backend Django.
We will create an app called 'contact' for our task and place it in the example django project. Urls from the project will redirect to this app. OK. Here is what in our:
urls.py
from django.conf.urls import patterns, url

urlpatterns = patterns('contact.views',
    url(r'^$', 'contact_form', name="contact_form"),
)
Here ve have only one view serving all the needs. and looking at the root of the app. Enough to prove the idea.

forms.py
from django import forms


class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField(max_length=100)
    message = forms.CharField(widget=forms.Textarea(), max_length=1000)
The form is far too simple. But quite sufficient for the concept proof.

views.py
import json

from django.shortcuts import render
from django.http import HttpResponseBadRequest
from django.http import HttpResponse
from django.core.mail import mail_admins
from forms import ContactForm


def contact_form(request):
    if request.POST:
        form = ContactForm(request.POST)
        if form.is_valid():
            # Imaginable form purpose. Post to admins.
            message = """From: %s <%s>\r\nMessage:\r\n%s\r\n""" % (
                form.cleaned_data['name'],
                form.cleaned_data['email'],
                form.cleaned_data['message']
            )
            mail_admins('Contact form', message)

            # Only executed with jQuery form request
            if request.is_ajax():
                return HttpResponse('OK')
            else:
                # render() a form with data (No AJAX)
                # redirect to results ok, or similar may go here 
                pass
        else:
            if request.is_ajax():
                # Prepare JSON for parsing
                errors_dict = {}
                if form.errors:
                    for error in form.errors:
                        e = form.errors[error]
                        errors_dict[error] = unicode(e)

                return HttpResponseBadRequest(json.dumps(errors_dict))
            else:
                # render() form with errors (No AJAX)
                pass
    else:
        form = ContactForm()

    return render(request, 'contact/form.html', {'form':form})
Here we will stop in more detail. We will work out all form possible conditions. e.g. valid/invalid and ajax/plain.
The main form purpose is to actually send a email to admins about contact request for our imaginable site (mail_admins() command and message being created from submitted data).
We have 2 form view conditions here. GET (When we load start of this page) and POST (When we upload the data and parse the form).
In case this view would not have the AJAX part it will look like so:
def contact_form(request):
    if request.POST:
        form = ContactForm(request.POST)
        if form.is_valid():
            # Imaginable form purpose. Post to admins.
            message = """From: %s <%s>\r\nMessage:\r\n%s\r\n""" % (
                form.cleaned_data['name'],
                form.cleaned_data['email'],
                form.cleaned_data['message']
            )
            mail_admins('Contact form', message)
    else:
        form = ContactForm()

    return render(request, 'contact/form.html', {'form':form})
This view works normally with provided template and disabled JavaScript scripts in the template (you may compare it to the first view with AJAX additions). I have not used common possibilities, because I do not need them for demo. It's up to you to decide where to make redirect or so.
Note we are using here request.is_ajax() method and adding another dynamic web page functionality, thus making view behave right for our AJAX needs. And the logic goes into another direction when commented (No AJAX).  Here is where our logic changes go when we do not use jQuery form for request.
Errors here are treated specially. We need the field names of them and the error html to modify for4m in the frontend JavaScript.
Now I hope you understood what is made here. Now let's move on to the templates.
<!DOCTYPE html>
<head>
    <title>Contact</title>
    <script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js">
    </script>
    <script type="text/javascript"
        src="http://malsup.github.com/min/jquery.form.min.js">
    </script>
    <script type="text/javascript">
        $(document).ready(function() {
            function block_form() {
                $("#loading").show();
                $('textarea').attr('disabled', 'disabled');
                $('input').attr('disabled', 'disabled');
            }

            function unblock_form() {
                $('#loading').hide();
                $('textarea').removeAttr('disabled');
                $('input').removeAttr('disabled');
                $('.errorlist').remove();
            }

            // prepare Options Object for plugin
            var options = {
                beforeSubmit: function(form, options) {
                    // return false to cancel submit
                    block_form();
                },
                success: function() {
                    unblock_form();
                    $("#form_ajax").show();
                    setTimeout(function() {
                        $("#form_ajax").hide();
                    }, 5000);
                },
                error:  function(resp) {
                    unblock_form();
                    $("#form_ajax_error").show();
                    // render errors in form fields
                    var errors = JSON.parse(resp.responseText);
                    for (error in errors) {
                        var id = '#id_' + error;
                        $(id).parent('p').prepend(errors[error]);
                    }
                    setTimeout(function() {
                        $("#form_ajax_error").hide();
                    }, 5000);
                }
            };

            $('#ajaxform').ajaxForm(options);
        });
    </script>
    <style>
        #form_ajax_error, .errorlist {
            color: red;
        }
    </style>
</head>
<body>
    <h1>Contact</h1>
    <form id="ajaxform" action="{% url contact_form %}" method="post">
        {% csrf_token %}
        {{ form.non_field_errors }}
        {{ form.as_p }}
        <div id="loading" style="display:none;">
            <span id="load_text">loading...</span>
        </div>
        <div id="form_ajax" style="display:none;">
            <span>Form submit successfully.</span>
        </div>
        <div id="form_ajax_error" style="display:none;">
            <span>Can not submit data due to errors.</span>
        </div>
        <p id="sendwrapper"><input type="submit" value="Send" id="sendbutton"/></p>
    </form>
</body>
</html>
Here I have all the script encoded for show purposes. However it is a bad practice. You should not do it in a real life project.
Here we render the form with default django tags and add 3 conditional form help text messages.
They will display and lightly fade after 5 seconds. Saying either script have submitted/loading/errors returned state.
They are controlled with the jQuery script. We also disabling the entire form with all the elements while AJAX is working. SO user can not change the data accidently.
The plugin itself is binded to the form with jQuery command $('#ajaxform').ajaxForm(options). It uses options object created earlier. Here we have 3 condition handlers, as functions. We are locking the form and displaying the loading text (beforeSubmit), submit succeeded (success) and the most interesting one is error handling function (error). It parses JSON provided by the backend in case of errors. Then modifying the DOM with provided errors, relying on the django form rendering logic to find the "id" of the HTML input that needs an error prepended.
Our form will look like so:

I have collected everything in a git repository. You can clone/copy and run it for yourself. The app has some hooks for debug to slow down request/response. So you will be able to see loading state, etc...
Repository with working copy from this app is here:
https://github.com/garmoncheg/ajax_form_example

Comments? Suggestions?

Nov 9, 2013

CouchDB restoring deleted/updated documents and their data

We are using CouchDB for production and happy with it. It is much more lightweight rather then MongoDB yet powerful. (For our needs at least). But sometimes you have situations that some code deleted/spoiled your Couch Database data. We had some bugs leading to deleting indexes. However compaction have not been run and here is the decision.

There are several ways for different situations. I'll try to cover them all.
So for deleted CouchDB documents you need to:

1. Make sure your document with this id is Deleted.

To do it you need to request CouchDB for this document. E.g. with this string:
$db/$id
Where $db is your CouchDB database name and $id is your deleted document id
it should return something like this:
{"error":"not_found","reason":"deleted"}

2. Get all the revisions of the deleted document.

With this request:
$db/$id?revs=true&open_revs=all 
Where $db is your CouchDB database name and $id is your deleted document id.

3. Parse response.

CouchDb provides a response with revisions in a special coded format. So to parse this JSON response you need to know it's syntax. It's fairly simple.
 Content - Type: application / json

 {
    "_id": "my-couchdb-id",
    "_rev": "6-65624dd5962e59ff09c47ba1be4f726c",
    "_deleted": true,
    "_revisions": {
        "start": 6,
        "ids": ["65624dd5962e59ff09c47ba1be4f726c", "826046dbd125b841e0dba657f65bbb78", "d1485b8d5cccc305f1dbccf65a07199d", "e1293576c567836c80cd973f36d345aa", "2bbc0c49496d3044c80b824be7e30193", "0aa0c2ce9796de25733b0cf46ee15129"]
    }
}
You can get multiple JSON's like I did. Because document was deleted and undeleted several times.
Anyway. here we have a JSON indicating current (last before deletion) revision of the document. ("_rev": "6-65624dd5962e59ff09c47ba1be4f726c",  ) Let's try to recover it.

4. Find out required revision hash.

Note "_revisions" key in later JSON, containing a list of "ids". Note first one has the same revision hash as the last revision. Our target is previous revision (before deletion). E.g. Or latest one if the document we are trying to recover was just updated, but not deleted. We might need next revision code.
SO in our example:
 "ids": ["65624dd5962e59ff09c47ba1be4f726c",
First one is equal to current and the next one is before it.
Note also key start ("start": 6, ). It indicates latest revision counter. You could stick to that. E.g. subtract 1 from latest revision and add it to the second hash with "-". So to recover previous revision you would need to create a code like this: "5-826046dbd125b841e0dba657f65bbb78". Hope you have understood about how have I come to this.

5. Retrieve previous revision.

To do that just ask couch with address:
$db/$id?rev=$previous_revision
Where $db and $id are your previous database name and deleted code, but $previous_revision is obviously your constructed revision counter + revision hash separated by the "-" symbol. 5-826046dbd125b841e0dba657f65bbb78 In our case.
We will get JSOn of a previous document (before deletion). And we may put it back with PUT/POST request.

It's also worth to mention about when you do not know what revision and/or document $id you want to recover. And want to just recover e.g. previous 10 deleted documents. Then you need to look at request:
$db/_changes
It will provide a list of documents manipulations in the database. It's simple enough. But behind the scope of this article.

That's basically it. Questions/comments?

Nov 6, 2013

OS X Mavericks and Last.FM scrobling of iTunes radio


I have used iTunes radio dramatically after installing a new version of iTunes. But the problem is my musical taste is recorded (Historically) at Last.FM profile. So It is something like combining your Last.FM profile with your iTunes Geniuos data. AFAIK iTunes uses it's data to play songs in a given station. After trying several decisions I have found a nice one that simply works.

You need an app called Bowtie. It's built for older OS X'es. But works nicely for this purpose. It has a themed desktop applet. So it's something like a nice bonus. Anyway you can connect it with Last.FM and that's it. Just one thing it sits in your memory. But I have found it does not consume too much resources or has obvious flaws that spoil Mac anyway.
One trick to install it you need to enable it install your system. It is not from apple store so...
as per stackoverflow question it can be done like so:

Go to System Preferences... > Security & Privacy and there should be a button saying Open Anyway, under the General tab.
Original answer at stackoverflow.com

So that's basically it. Enjoy.

Aug 22, 2013

install ssh-copy-id on Mac OS X best way

You often need to create identities for unknown/new servers. Then welcome to this article. I believe i have a best practice way of doing it on a MAC system.
First of all you need your identity file:

1. Generating ssh keys set

You need to use tool that any unix system usually has. It's ssh-keygen. (Skip if you have it already)
Last login: Wed Aug 21 16:07:34 on ttys002
console@username:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/username/.ssh/id_rsa): yourkeyname
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in yourkeyname.
Your public key has been saved in yourkeyname.pub.
The key fingerprint is:
XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX. console@username
The key's randomart image is:
+--[ RSA 2048]----+
|    +             |
|   +              |
|         +        |
| +                |
|     +            |
|   . +            |
|  . +             |
|   . ...........+ |
|    . .+....      |
+-----------------+
console@username:~$
Note this command input/output. You need to call command ssh-keygen -t rsa and generate a key on your computer. You could do it in some other way, for e.g. on a server. In this example we create 2 SSH keys. They both have yourkeyname in it's body. Except for one is public and called yourkeyname.pub. And you may share your public key, but never share your private. But it;s about simplifying install not cheap talks.
Let's copy your public key to server after you have your suitable key pair.

2. Copy to ssh public key to server

This step is not required and you could easily skip it. However it may already be done at your MAC.
Now let's copy your key with extension .pub to remote server. You could do it manually, but in case of this happening too often it may turn you nuts to type in those letters.
Github user  beautifulcode created a nice script to make your MAC OS X behave like linux in this occasion. I have forked it just in case and gonna use mine forked version farther. However all the credentials belong to author ;).
Ok. For all this to work you need to actually type in 2 commands into console:
https://raw.github.com/garmoncheg/ssh-copy-id-for-OSX/master/ssh-copy-id.sh
chmod +x /usr/local/bin/ssh-copy-id
This will download a script body from a github server (my fork) and change it's credentials to execution mode.

Now this is done and you can use your linux-like command style in MAC OS X. It may look like this.
ssh-copy-id -i yourkeyname.pub username@remoteservername
This will ask for password to your remote ssh server and user: username in our case.
3. Create an alias for your server
It's a long time to type in ssh yourusername@yourserver.com and you can shorten this to ssh srv for e.g. For this you need to create the alias in your ssh keys config.
To make it you need to enter your ~/.ssh directory and edit/create file called config. So type in something like:
console@username:~$ vi ~/.ssh/config
And edit it somehow like so:
# Add this to file
Host srv
                Hostname servername_or_ip
                User username
                IdentityFile ~/.ssh/yourkeyname
Save it (:wq if you use vim). And I recommend using the text editor of your choice, instead.
Now you have to only type ssh srv and here is your remote shell. But please keep in mind responsibility that lies on your shoulders with this. Intruder having your computer receives all the access you would have.

Comments?

Aug 6, 2013

Django: Add Permission model to admin panel

How to add a permissions model to your Django admin?
You may add those lines to anywhere in your code. But it is more convinient to add this to your admin.py or place where django admin custom code lies. Here are them:
from django.contrib.auth.models import Permission
admin.site.register(Permission)
Now you can manage them in in your Django admin panel. May look like this:
Hope this helps.

Jul 23, 2013

How to burn (write) an ISO image to USB drive in all new Mac OS X systems

There are many programs in the market that can handle it for you. But you can do it with default Mac OS X tools. Those steps must be made in terminal. You need to know what you are doing and have root password to your system.
Here is your step by step guide to do it:


1. Convert your image.

You need to change the image type from .iso to .img that dd util supports. To do this type a command like this:
hdiutil convert -format UDRW -o /path/to/destination/file.img /path/to/source/file.iso
You must see output similar to this:
Reading Image File Name Here  (Apple_UDF : 0)…... [ truncated ] .............................
Elapsed Time:  4m 57.725s
Speed: 20.9Mbytes/sec
Savings: 0.0%
created: /path/to/image/file.img.dmg

2. Remove the .dmg extension.

mv /path/to/image/file.img.dmg /path/to/image/file.img

3. Get your flash drive device name.

You can do it in various ways. one that is using standard utils here:
diskutil list
This will list all your disks mounted to your mac. Output should be similar to this:
$ diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *750.2 GB   disk0
   1:                  Apple_HFS Vault                   750.2 GB   disk0s1
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *128.0 GB   disk1
   1:                        EFI                         209.7 MB   disk1s1
   2:                  Apple_HFS Mac OS HD               127.2 GB   disk1s2
   3:                 Apple_Boot Recovery HD             650.0 MB   disk1s3
/dev/disk3
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *16.0 GB    disk3
   1:                 DOS_FAT_32 UNTITLED                16.0 GB    disk3s1
So in my case flash drive is named disk3. Note it is not disk3s1, that indicates a partition name not a drive name.

4. Unmount your flash drive.

Note you need to unmount, not eject this flash drive. Command may be like so:
diskutil unmountDisk /dev/disk3
Change that disk3 to your device id.

4. Write your image to flash drive.

To handle this you would use a dd utility. Note param bs=1m, indicating block size to write. Missing this parameter would force dd to run byte by byte copy, resulting run for ages with several gigs of data.
sudo dd if=/path/to/image/file.img of=/dev/rdisk3 bs=1m
Note to change that disk3 to your flash drive id.
You may use rdisk instead of dd to add some speed to this. But this particular run was ok for me.
You may see an output like this, resulting you may eject and use your flash drive farther.
$ sudo dd if=/path/to/image/file.img of=/dev/rdisk3 bs=1m
Password:
6207+1 records in
6207+1 records out
6509363200 bytes transferred in 1124.570118 secs (5788312 bytes/sec)

Hope this help somebody someday. Cheers.
Please comment and share!