Oct 10, 2011

Проверка состояния сервера и перезапуск в случае необходимости

Можно воспользоваться Supervisor или чем-то подобным, но для небольших проектов достаточно crontab:
crontab -e
Например, для проверки memcached каждую минуту:
*/1     *       *       *       *       netstat -ln | grep ":11211 " | wc -l | awk '{if ($1 == 0) system("/etc/init.d/memcached start") }'

Oct 5, 2011

Signals registration

Best place for Django signals is app/signals.py file. This snippet imports signal modules from all installed apps.
from importlib import import_module
from django.conf import settings

for app in settings.INSTALLED_APPS:
    try:
        import_module( 'signals', app)
    except ImportError as e:
        print 'Failed to import "%s", reason: %s' % (app, str(e)))
Original: http://djangosnippets.org/snippets/2561/

Sep 23, 2011

django_graceful

django_graceful - Плавный перезапуск FastCGI-процессов

Его идея проста: настройки FastCGI хранятся в файле settings.py, а для управления FastCGI-процессами используются простые команды из manage.py. Эти команды поддерживают несколько параллельно запущенных экземпляров FastCGI-сервера и позволяют переключать веб-сервер между ними с помощью символической ссылки на файл unix-socket-а, то есть без перезапуска веб-сервера.

Sep 20, 2011

Git housekeeping

git fsck # Verifies the connectivity and validity of the objects in the database
git prune # Prune all unreachable objects from the object database
git gc # Cleanup unnecessary files and optimize the local repository
git pack # Pack unpacked objects in a repository
git prune-packed # Remove extra objects that are already in pack files

Memcached telnet commands

telnet localhost 11211

flush_all # Flashes the entire cache
stats # General statistics
stats slabs # Memory statistics
stats memory # Memory statistics
stats items # Higher level statistics
quit # Quit the telnet interface

Sep 14, 2011

Python property object has getter, setter, and deleter methods

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

Sep 1, 2011

Unix as IDE. Сетевые утилиты

netstat

Показывает сетевые соединения (входящие/исходящие), таблицу маршрутизации, статистику по сетевым интерфейсам и т.д.
netstat -at # Список всех открытых портов (TCP)
netstat -au # Список всех открытых портов (UDP)
netstat -nagrep 22 # Список открытых хостов по порту
netstat -lt # Список только прослушиваемых портов (TCP)
netstat -s # Статистика по всем открытым портам
# Подробное отображение списка с открытыми портами - добавлен PID и имя процессов
netstat -p 
# Команда для просмотра открытых TCP/UDP портов с именами процессов
# (может понадобиться root-доступ)
netstat -ltupn 
# Список подключенных хостов
netstat -lantp | grep ESTABLISHED |awk '{print $5}' | awk -F: '{print $1}' | sort -u

ss

Позволяет просматривать информацию об используемых сокетах в системе. Эта команда обладает схожим функционалом c netstat, но есть и уникальные возможности. Например возможность фильтровать вывод по установленным соединениям с определенным портом.
ss -p  # Список процессов, использующие соединения в данный момент
ss -l # Список сокетов в режиме прослушивания
 # Пример фильтра - список всех соединений к порту 80
ss -o state established '( dport = :www or sport = :www )'

lsof

Отображает процессы, которые работают с определенным файлом или сокетом.
lsof -i # Список всех сетевых соединений
lsof -i :80 # Список процессов, работающих с портом 80

netcat

Позволяет передавать/принимать данные через TCP/UDP соединения.
# Передача файла
nc -l 1234 > file # На принимающей стороне
nc localhost 1234 < file # На отправляющей стороне

# Или отдавать файл любому подключившемуся
nc -l 1234 < file # На передающей стороне
nc localhost 1234 > file # На принимающей стороне

nmap

Cканирует IP-сети с любым количеством объектов, определяет состояние объектов сканируемой сети (портов и соответствующих им служб).
Для работы большинства возможностей nmap требуется права root. Разработчики nmap предлагают хост scanme.nmap.org для тестового сканирования.
# Получение информации об портах удаленного хоста и определение операционной системы
sudo nmap -sS -P0 -sV -O scanme.nmap.org 
# scanme.nmap.org – сканируемый хост, может быть: IP, имя хоста или подсеть
# -sS – TCP SYN сканирование (полуоткрытое)
# -P0 – отключение ICMP сканирования
# -sV – определение сервисов, запущенных на открытых портах
# -O – определение версии операционной системы

# Пингование диапазона адресов
sudo nmap -sP -v "192.168.1.*" 
sudo nmap -sP -v 192.168.1.0/24
sudo nmap -sP -v 192.168.1.1-20
# -sP - ping-сканирование

sudo nmap -sT -p 22 scanme.nmap.org # Проверка одного порта
sudo nmap -sT -p 20-110 scanme.nmap.org # Проверка диапазона портов
# -sT - TCP-сканирование

sudo nmap -sS scanme.nmap.org -D 8.8.8.8 # Cкрыть свой IP адрес

nmap localhost # Определения открытых портов на локальной машине нужно выполнить

fuser

Принудительное закрытие определенного порта
fuser -k 80/tcp

DNS lookup

http://greendail.ru/node/474
dig  www.podkova.by  +trace

nslookup podkova.by
# or using google ns server
nslookup podkova.by 8.8.8.8

tshark

You can use the specific HTTP header display filters to show either just the request headers, just the response headers or both.
tshark tcp port 80 -V -R "http.request || http.response"

curl

curl \
  -s -u <USER>:<API_TOKEN> \
  -d '{ "id": "ce9d27f8", "method": "getContact", "params": [77777] }' \
  https://app01.nutshell.com/api/v1/json | python -m json.tool

# with Headers
curl -H 'Authorization: OAuth <SECURE_TOKEN>' https://blabla.com/api/?var=foo

# GET request (-G) with data (-d)
curl -G \
  -d 'access_token=77777777777777777777' \
  -d 'page=1' \ 
  -d 'per_page=1' \
  https://api.nimble.com/api/v1/contacts/list
How to test request to django-tastypie API using ApiKey:
curl \
  -H 'Authorization: ApiKey someusername:83a82c7941f6dba06510541c71505c71a0625741' \
  -H 'Content-Type:application/json' \
  -X PATCH -d '{"first_name" : "bob","last_name" : "marley"}' \
  http://127.0.0.1:8000/api/profile/

Aug 31, 2011

SSH aliases

Чтобы заходить на сервер при помощи простой комманды ssh somealias в ~/.ssh/config прописывается:
Host somealias
  HostName 11.111.11.111 
  User root

Еще удобно сгенерировать ключ

Aug 30, 2011

Django Admin Snippets

readonly_field

As of Django 1.2, a readonly_field has been available to models in the admin. This is very helpful for making data visible in the admin while preventing it from being edited.

readonly_fields=[’created’,’modified’,’preformed_by’,’ipaddress’,’featured’]

get_readonly_fields()

Using the get_readonly_fields() method of the ModelAdmin, one can change readonly fields dynamically. The method gives access both to the request and to the Admin Model instance.

def get_readonly_fields(self, request, obj = None):
    if obj: 
        if not (request.user.is_staff or request.user.is_superuser):
            return [‘featured’,] + self.readonly_fields
        return self.readonly_fields
    else:
        return self.readonly_fields

Disable admin actions

By default, every Django Admin model has a delete_selected admin action available which allows admins to delete multiple objects in the change_list admin view. If you wish to remove this default option and disable all the admin actions for a given Django Model in the Admin, something like this may be appropriate. This will remove the “Actions” dropdown completely from the model’s change list.

admin_actions = None

Override get_actions

An alternative to disabling all the admin actions for a Model would be to override the get_actions() method on the ModelAdmin. This will allow you to customize the “Actions” list based on the request or other factors.
http://stackoverflow.com/questions/1565812/the-default-delete-selected-admin-action-in-django

def get_actions(self, request):
    actions = super(PostAdmin, self).get_actions(request)
    try:
        del actions[‘delete_selected’]
    except KeyError:
        pass 
    return actions

Customize permissions

The has_delete_permission() ModelAdmin method allows you to customize how permissions are assigned for a given model in the admin. Instead of using Django’s default permission system, you can change the permissions programmatically. Note that this function does not change how permissions work on admin actions such as the delete_selected action discussed above.

def has_delete_permission(self, request, obj=None):
    return_value = False
    user = request.user
    if user.is_authenticated() and user.is_staff:
        return_value = True
    return return_value

The has_add_permission() allows the same type of customization of permissions for adding objects.

def has_add_permission(self, request):
    return_value = False
    user = request.user
    if user.is_authenticated() and user.is_superuser:
        return_value = True
    return return_value

Customize save_model

The save_model() method allows you to customize actions that take place on the model only when it’s saved in the admin. In this example, we override the save_model() so that we may save to the model of the current admin user and her IP address.

def save_model(self, request, obj, form, change):
    obj.preformed_by = request.user
    obj.ip_address = utils.get_client_ip(request)
    obj.save()

Change multiple-select widget to filter_horizontal for ManyToMany fields

When dealing with ManyToMany fields, the default admin widget is a multiple-select box which allows a user to control-select a list of multiple items. This select box is kind of awkward; a better option may be to use the Filter Horizontal widget which provides a more advanced box.

filter_horizontal = ('category',)

For performance reasons use raw_id_fields instead filter_horizontal

For performance reasons, it may not be a good idea to use the Django default widget or the filter_horizontal widget for ManyToMany relations where a lot of related results. For example, a filter_horizontal Admin widget may take a long time to load if used to display a related tags field if there are thousands of possible related Tags. In that case, the raw_id_fields Admin option may be more appropriate, as it will only display the ID field and unicode representation of the related object. This option also provides a link to a popup dialog that allows an admin to populate the id field by browsing for an object interactively.

raw_id_fields = ("tags",)

Dynamically define fieldsets

The Django Admin offers some flexibility in how the fields on the detail pages are displayed. Fieldsets are used to group Admin fields into sections and even together on the same line. This can be done dynamically by overriding the __init__() on the ModelAdmin.

fieldsets = []
  
def __init__(self, model, admin_site):    
    # Define some field groupings
    post_fields = ['title', 'type', 'featured']
    meta_fields = ['created', 'modified',]
    client_fields = ['preformed_by', 'ipaddress']
    message_fields = ['message',]       

    # make a big list of all the fields that we are customizing 
    ex_fields = post_fields + meta_fields + client_fields + message_fields
    all_fields = fields_for_model(model)
      
    base_fields = [tuple(post_fields), tuple(meta_fields), tuple(message_fields)]
 
    # all the rest of the fields that we don’t specifically customize
    rest_fields = list(set(all_fields) - set(ex_fields))
 
    # Group fields into Sections
    self.fieldsets.append(('Post Info', { 'fields': tuple(base_fields), }))
    self.fieldsets.append(('Client Info', { 'fields': tuple(client_fields), }))
        
    # Display the rest of the non-customized fields at the bottom
    if rest_fields:
        self.fieldsets.append(('Other', { 'fields': tuple(rest_fields), }))

    # set the fieldset - needs to be a tuple 
    self.fieldsets = tuple(self.fieldsets)

    super(PostAdmin, self).__init__(model, admin_site)

admin.site.register(models.Post, PostAdmin)

Customize User model

Sometimes it’s nice to be able to customize the admin page for the Django user. This can be done by un-registering the default ModelAdmin class and re-registering your customized version. This code should be placed in any one of your Django App’s admins.py files. In this example, we add a custom Inline class to the User Admin, as well as modify the list_display and list_filter fields for the User Admin.

from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

class PostInline(admin.TabularInline):
    model = models.Post
    extra = 0
    readonly_fields = ['created', 'modified', 'preformed_by', 'ip_address']
    exclude = ['tags','category',]

class CustomUserAdmin(UserAdmin):
    list_display = UserAdmin.list_display + ('date_joined','last_login')
    list_filter = UserAdmin.list_filter + ('is_active',)
    inlines = [PostInline,]

admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

Customize User form

The form that an Admin model uses can be customized as well. For example, you can place extra validation on the Admin form to ensure that the admin users enter data correctly.

class PostAdminForm(forms.ModelForm):
    class Meta:
        model =  models.Post

    def clean(self):
        cleaned_data = self.cleaned_data
        message = cleaned_data.get("message", False)

        if len(message) < 20:
            raise forms.ValidationError("Message must be 20+ chars long.")

        return cleaned_data

Set the form by adding it to the PostAdmin ModelAdmin.

class PostAdmin(admin.ModelAdmin):
   ...
   ...   
   form = PostAdminForm 
   ...

Override “Django Administration”

One convenient admin customization is to override the default “Django Administration” title that appears at the top of the admin interface. This can be done via an admin template override.

Let’s say our settings.py has our TEMPLATE_DIRS set as follows, where PROJECT_PATH is the UNIX filesystem path to the Django Project.

import os
PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))
TEMPLATE_DIRS = (
   os.path.join(PROJECT_PATH, 'templates'),
)

We could create a file called base_site.html located in PROJECT_PATH/templates/admin/ which contains the following Django template code. This overrides the default title for the Django admin.

{# Located in PROJECT_PATH/templates/admin/base_site.html #}

{% extends "admin/base.html" %}
{% load i18n %}

{% block title %}{{ title }} | {% trans 'ChicagoDjango Demo Project Admin' %}{% endblock %}

{% block branding %}
<h1 id="site-name">{% trans 'ChicagoDjango Demo Project Administration' %}</h1>{% endblock %}

{% block nav-global %}{% endblock %}

Add extra “sections” to the Django admin on a given Object Change page

Sometimes you may want to add extra “sections” to the Django admin on a given Object Change page (change_form.html). This can be done with an admin template override and template inheritance. In order to override the default admin template for the Object Change view, you need to place a file named change_form.html in the following directory within your Django module directory, where your_module_name and your_model_name refers to the lower-case names of your Django module and Django model respectively: templates/admin/<your_module_name>/<your_model_name>/.

Notice in the code below that this custom template overrides admin/change_form.html. Also, this custom template defines a block called {% block after_field_sets %} which adds a template block at the bottom of the page. You can reference the object being edited as a context variable called “original”.
</your_model_name>/<your_module_name>

{# Located in MODULE_PATH/templates/admin/a/post/change_form.html #}

{% extends "admin/change_form.html" %}

{% block extrahead %}{{ block.super }}
<style>
  .item { padding: 10px; border-bottom:1px solid #EEEEEE; height: 25px }
  .heading { font-weight: bold; font-size: 14px; color: #666666;  }
</style>
{% endblock %}

{% block after_field_sets %}{{ block.super }}

<div class="module aligned">
    <div class="item">Post: {{ original.title }}</div>
</div>

<div class="module aligned">
    <div class="item heading">Post Categories</div>
    {% for category in original.category.all %}  
    <div class="item">
        <span class="item_name">{{ category.name }}</span>
        <span class="item_edit"><a href="{% url admin:a_postcategory_change category.id %}" target="_blank">Edit</a></span>
    </div>
    {% empty %}
    <div class="item">No Categories</div>{% endfor %}
</div>
{% endblock %}

When it comes to customizing the Django admin, this is just the tip of the iceberg. Please feel free to share any admin customizations that you find interesting via a comment. Also, feel free to fork the Github repository and suggest updates or additional techniques.

Original http://www.chicagodjango.com/blog/django-admin-snippets/

Aug 25, 2011

Benchmark page

ab -n 1000 -c 10 "http://127.0.0.1:8000/"
# -n  number of requests to perform for the benchmarking session. The default is to just perform a single request which usually leads to non-representative benchmarking results.
# -c  number of multiple requests to perform at a time. Default is one request at a time.