Thursday, June 25, 2015

[Django] Changing field widget when when using inlines

For example, if you create a SiteOption model to extend Django's core sites framework you may want to add multiple inlines from one model (SiteOption) for grouping options, like:

General Options
Theme Options
Security Options
SEO Options

"Show me the code!"

from django import forms
from django.contrib import admin
from django.contrib.sites.models import Site
from django.contrib.sites.admin import SiteAdmin
from django.utils.translation import ugettext_lazy as _
from colorful.fields import RGBColorField # third-party app
from .models import SiteOption
OPTION_COLOR_VARIABLE_CHOICES = (
('header_color', _('Header Color')),
# ...
)
OPTION_VARIABLE_CHOICES = (
('contact_email', _(u'admin@site.com')),
# ...
)
# Register site option model as inline into sites
# by unregistering Site model first
class ThemeColorsInlineAdmin(admin.TabularInline):
model = SiteOption
verbose_name = _('Theme Color')
verbose_name_plural = _('Theme Colors')
extra = 0
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.attname == 'variable':
# Change variable field's widget with selectbox!
kwargs['widget'] = forms.Select(
choices=OPTION_COLOR_VARIABLE_CHOICES)
if db_field.attname == 'value':
# change value field's widget with color picker!
db_field = RGBColorField()
return super(ThemeColorsInlineAdmin, self).formfield_for_dbfield(
db_field, **kwargs)
def get_queryset(self, request):
"""
Limit result to get only color variables.
"""
qs = super(ThemeColorsInlineAdmin, self).get_queryset(request)
return qs.filter(variable__in=[f[0] for f in OPTION_COLOR_VARIABLE_CHOICES])
class SiteOptionInlineAdmin(admin.TabularInline):
model = SiteOption
extra = 0
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.attname == 'variable':
# Change variable field's widget with selectbox!
kwargs['widget'] = forms.Select(choices=OPTION_VARIABLE_CHOICES)
return super(SiteOptionInlineAdmin, self).formfield_for_dbfield(db_field, **kwargs)
def get_queryset(self, request):
"""
Limit result to get only non-color variables.
"""
qs = super(SiteOptionInlineAdmin, self).get_queryset(request)
return qs.exclude(variable__in=[f[0] for f in OPTION_COLOR_VARIABLE_CHOICES])
class MySiteAdmin(SiteAdmin):
inlines = [ThemeColorsInlineAdmin, SiteOptionInlineAdmin]
admin.site.unregister(Site)
admin.site.register(Site, MySiteAdmin)
view raw admin.py hosted with ❤ by GitHub
from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager
class SiteOption(models.Model):
variable = models.CharField(max_length=80)
value = models.TextField()
site = models.ForeignKey(Site)
objects = models.Manager()
on_site = CurrentSiteManager()
class Meta:
unique_together = (('variable', 'site'),)
view raw models.py hosted with ❤ by GitHub

Wednesday, June 17, 2015

[Django] Using cloud storage services as default storage backend

To use cloud storage services as default storage backend in Django – or actullay in Python, Apache's Libcloud wrapper can be a nice solution. Because it supports more than 30 providers, and has a huge community.

django-storages-redux app provides storage backends to use in Django. Good news, also supports Apache Libcloud. So you can use more than 30 cloud providers with Django. To install the app execute this:
$ pip install django-storages-redux
Also you must install Apache Libcloud:
$ pip install apache-libcloud
And enable from settings.py by adding following lines:
DEFAULT_FILE_STORAGE = 'storages.backends.apache_libcloud.LibCloudStorage'
DEFAULT_LIBCLOUD_PROVIDER = 'google_storage'
LIBCLOUD_PROVIDERS = {
 'google_storage': {
 'type': 'libcloud.storage.types.Provider.GOOGLE_STORAGE',
 'user': 'yourcloudstorageapikey:)',
 'key': 'yourcloudstorageapisecretkey:)',
 'bucket': 'default-bucket-name',
 }
}
 If you don't create bucket, you can create from shell:
$ ./manage.py shell

$ from storages.backends.apache_libcloud import LibCloudStorage
$ LibCloudStorage('google_storage').driver.create_container('default-bucket-name')

Wednesday, June 10, 2015

Detecting if an image is really an image

About Technique

HTTP protocol has really cool methods such as HEAD. HEAD method allows you to get only head data instead of head and body. Head data contains mimetype of the body, so we can rely on it to detect if it's really an image. Let's get it with JavaScript...

The Code

Sync Example

request = new XMLHttpRequest()
request.onreadystatechange = ->
if request.readyState is 4
mimetype = request.getResponseHeader('content-type')
if mimetype.split('/').shift() is 'image'
alert 'Image!'
else
alert 'Not Image!'
request.open 'HEAD', 'http://upload.wikimedia.org/wikipedia/commons/5/5b/Ultraviolet_image_of_the_Cygnus_Loop_Nebula_crop.jpg', true
request.send()
view raw async.coffee hosted with ❤ by GitHub

Async Example

request = new XMLHttpRequest()
request.onreadystatechange = ->
if request.readyState is 4
mimetype = request.getResponseHeader('content-type')
if mimetype.split('/').shift() is 'image'
alert 'Image!'
else
alert 'Not Image!'
request.open 'HEAD', 'http://upload.wikimedia.org/wikipedia/commons/5/5b/Ultraviolet_image_of_the_Cygnus_Loop_Nebula_crop.jpg', true
request.send()
view raw async.coffee hosted with ❤ by GitHub

As you can see, you can even detect huge images very quickly. ;)

Originally posted at https://coderwall.com/p/qdg71a/detecting-if-an-image-is-really-an-image