Update cached sublocations for added or removed location parent .

def update_parent_location_list(location):
    """ Update cached sublocations for added or removed location parent. """
    if location.parent is not None and settings.USE_CACHE:
        for language in [x[0] for x in settings.LANGUAGES]:
            key = "{}_{}_sub".format(location.parent.slug, language)
            redis_cache.set(key, location.parent.location_set.all())

def update_parent_location_list ( location ) : if location . parent is not None and settings . USE_CACHE : for language in [ x [ 0 ] for x in settings . LANGUAGES ] : key = "{}_{}_sub" . format ( location . parent . slug , language ) redis_cache . set ( key , location . parent . location_set . all ( ) )


Returns results for autocomplete widget .

def get(self, request):
        """ Returns results for autocomplete widget. """
        if request.is_ajax():
            fields = ('id', 'name', 'slug', 'parent', 'country_code',)
            term = request.GET.get('term', '')
            locations = self.model.objects.filter(name__icontains=term)
            context = serializers.serialize("json", locations, fields=fields)
            return HttpResponse(context, content_type="application/json")
        return super(LocationListView, self).get(request)

def get ( self , request ) : if request . is_ajax ( ) : fields = ( 'id' , 'name' , 'slug' , 'parent' , 'country_code' , ) term = request . GET . get ( 'term' , '' ) locations = self . model . objects . filter ( name__icontains = term ) context = serializers . serialize ( "json" , locations , fields = fields ) return HttpResponse ( context , content_type = "application/json" ) return super ( LocationListView , self ) . get ( request )


def get_object(self, pk):
        """ Get location object from db. """
        if not self.object:
            self.object = Location.objects.get(pk=pk)
        return self.object

def get_object ( self , pk ) : if not self . object : self . object = Location . objects . get ( pk = pk ) return self . object


def get(self, request, pk):
        """ Create invite form. """
        location = self.get_object(pk)
        form = InviteUsersForm(initial={'location': location})
        return render(request, self.template_name, {
            'location': location,
            'form': form,
        })

def get ( self , request , pk ) : location = self . get_object ( pk ) form = InviteUsersForm ( initial = { 'location' : location } ) return render ( request , self . template_name , { 'location' : location , 'form' : form , } )


def post(self, request, pk):
        """ Send message to selected users. """
        users = request.POST.getlist('user[]')
        if users:
            for u in users:
                user = User.objects.get(pk=u)
                translation.activate(user.profile.lang)
                # Send email
                email = mails.InviteUsersMail()
                email.send(user.email, {
                    'inviting_user': request.user,
                    'location': self.get_object(pk),
                })
                # Record action for actstream
                action.send(
                    request.user,
                    action_object = self.get_object(pk),
                    target = user,
                    verb = _("invited you to follow")
                )
            ctx = {
                'success': True,
                'message': _("Successfully send invitation"),
                'level'  : 'success',
            }
        else:
            ctx = {
                'success': False,
                'message': _("User field cannot be empty"),
                'level'  : 'danger',
            }
        return HttpResponse(json.dumps(ctx))

def
post
(
self
,
request
,
pk
)
:
users
=
request
.
POST
.
getlist
(
'user[]'
)
if
users
:
for
u
in
users
:
user
=
User
.
objects
.
get
(
pk
=
u
)
translation
.
activate
(
user
.
profile
.
lang
)
# Send email
email
=
mails
.
InviteUsersMail
(
)
email
.
send
(
user
.
email
,
{
'inviting_user'
:
request
.
user
,
'location'
:
self
.
get_object
(
pk
)
,
}
)
# Record action for actstream
action
.
send
(
request
.
user
,
action_object
=
self
.
get_object
(
pk
)
,
target
=
user
,
verb
=
_
(
"invited you to follow"
)
)
ctx
=
{
'success'
:
True
,
'message'
:
_
(
"Successfully send invitation"
)
,
'level'
:
'success'
,
}
else
:
ctx
=
{
'success'
:
False
,
'message'
:
_
(
"User field cannot be empty"
)
,
'level'
:
'danger'
,
}
return
HttpResponse
(
json
.
dumps
(
ctx
)
)


Get native translations for geo name objects .

def get_translation(geonameid, country_code):
    """ Get native translations for geo name objects. """
    translation = None
    try:
        c = CountryInfo.objects.get(code=country_code)
        lang = c.languages.split(',')[0].split('-')[0]
    except CountryInfo.DoesNotExist:
        lang = None
    if lang is not None:
        try:
            translation = AltName.objects.filter(geonameid=geonameid, language=lang)
            translation = translation[0].altername
        except IndexError:
            translation = None
    return translation

def get_translation ( geonameid , country_code ) : translation = None try : c = CountryInfo . objects . get ( code = country_code ) lang = c . languages . split ( ',' ) [ 0 ] . split ( '-' ) [ 0 ] except CountryInfo . DoesNotExist : lang = None if lang is not None : try : translation = AltName . objects . filter ( geonameid = geonameid , language = lang ) translation = translation [ 0 ] . altername except IndexError : translation = None return translation


This function takes AdminCode model instance as argument and creates city objects for entire region excluding city districts . Additionally function takes location made based on region as argument to pass as parent for created cities .

def load_region_data(region, r_location):
    """
    This function takes AdminCode model instance as argument and creates city
    objects for entire region, excluding city districts. Additionally function
    takes location made based on region as argument to pass as parent for
    created cities.
    """
    city = GeoName.objects.filter(admin1=region.code, country=region.country)
    # Country capital region
    main = city.filter(feature_code='PPLC')
    # Regular admin region (e.g. state or voivodeship)
    if not main.count(): main = city.filter(feature_code='PPLA')
    forbidden = [x.admin2 for x in main]
    bad_codes = ['PPLX','PPLC','PPLA']
    city = city.exclude(admin2__in=forbidden).exclude(feature_code__in=bad_codes)
    # Get back main city removed by former query
    city = city | main
    for c in city:
        try:
            chk = Location.objects.get(pk=c.pk)
            logging.info("Location already exists: %s. Skipping", chk.name)
            continue
        except Location.DoesNotExist:
            pass

        try:
            trans = get_translation(c.pk, region.country)
            if trans is None: trans = c.name
            nl = Location.objects.create(
                id = c.pk,
                name      = trans,
                creator   = admin,
                kind      = c.feature_code,
                parent    = r_location,
                latitude  = c.latitude,
                longitude = c.longitude,
                country_code = c.country,
                population   = c.population
            )
            nl.save()
            logging.info("Created location: %s", nl.name)
        except Exception as ex:
            logging.error("Error creating location: %s - %s", c.name, repr(ex))


This function takes existing country code as argument and creates hierarchy - country / district / cities .

def load_country_data(code):
    """
    This function takes existing country code as argument and creates
    hierarchy - country/district/cities.
    """
    code = code.upper()
    country_info = CountryInfo.objects.get(code=code)
    regions_info = AdminCode.objects.filter(country=code)
    # Create location for country
    try:
        l = Location.objects.get(pk=country_info.pk)
        logging.info("Location already exists: %s. Skipping", l.name)
    except Location.DoesNotExist:
        trans = get_translation(country_info.pk, code)
        if trans is None: trans = country_info.name
        l = Location.objects.create(
            id = country_info.pk,
            name = trans,
            kind = 'country',
            country_code = country_info.code,
            creator = admin,
            population = country_info.population
        )
        l.save()
        logging.info("Created country location: %s", l.name)
    # Create related country instance
    try:
        l_country = Country.objects.get(location=l)
        logging.info("Related country already exists: %s. Skipping", l.name)
    except Country.DoesNotExist:
        l_country = Country.objects.create(code=code, location=l)
        l_country.save()
        logging.info("Created related country: %s", l.name)
    # Create location for every admin area and load cities
    for region in regions_info:
        try:
            nl = Location.objects.get(pk=region.pk)
            logging.info("Region already exists: %s. Skipping.", nl.name)
        except Location.DoesNotExist:
            trans = get_translation(region.pk, region.country)
            if trans is None: trans = region.name
            nl = Location.objects.create(
                id = region.pk,
                name = trans,
                kind = 'region',
                country_code = country_info.code,
                parent = l,
                creator = admin
            )
            nl.save()
            logging.info("Created region location: %s", nl.name)
        load_region_data(region, nl)


This function updates location translations for registered languages .

def load_translation_data(location_pk=None):
    """ This function updates location translations for registered languages. """
    langs = [x[0] for x in settings.LANGUAGES]
    if location_pk is not None:
        queryset = Location.objects.filter(pk=location_pk)
    else:
        queryset = Location.objects.all()
    for l in queryset:
        alt = AltName.objects.filter(geonameid=l.pk,
                                      language__in=langs)
        for a in alt:
            try:
                chk = l.names.get(pk=a.pk)
                logging.info("Translation %s exists. Skipping", a.pk)
            except AlterLocationName.DoesNotExist:
                alt_name = AlterLocationName.objects.create(
                    altername = a.altername,
                    language = a.language,
                )
                alt_name.save()
                l.names.add(alt_name)
                l.save()
                logging.info("Created translation %s for %s",
                             alt_name.language, l.pk)

def
load_translation_data
(
location_pk
=
)
:
langs
=
[
x
[
0
]
for
x
in
settings
.
LANGUAGES
]
if
location_pk
is
not
:
queryset
=
Location
.
objects
.
filter
(
pk
=
location_pk
)
else
:
queryset
=
Location
.
objects
.
all
(
)
for
l
in
queryset
:
alt
=
AltName
.
objects
.
filter
(
geonameid
=
l
.
pk
,
language__in
=
langs
)
for
a
in
alt
:
try
:
chk
=
l
.
names
.
get
(
pk
=
a
.
pk
)
logging
.
info
(
"Translation %s exists. Skipping"
,
a
.
pk
)
except
AlterLocationName
.
DoesNotExist
:
alt_name
=
AlterLocationName
.
objects
.
create
(
altername
=
a
.
altername
,
language
=
a
.
language
,
)
alt_name
.
save
(
)
l
.
names
.
add
(
alt_name
)
l
.
save
(
)
logging
.
info
(
"Created translation %s for %s"
,
alt_name
.
language
,
l
.
pk
)


Loads entire data set for places above 1000 population .

def load():
    """ Loads entire data set for places above 1000 population. """
    for country in CountryInfo.objects.all():
        load_country_data(country.code)

def load ( ) : for country in CountryInfo . objects . all ( ) : load_country_data ( country . code )


Find nearest big city for given latitude and longitude .

def get_nearest_city(lat, lng):
    """ Find nearest big city for given latitude and longitude.
    """
    qs = Location.objects.filter(latitude__gte=lat-1,
                                 latitude__lte=lat+1,
                                 longitude__gte=lng-1,
                                 longitude__lte=lng+1)
    try:
        return qs.order_by('-population')[0]
    except IndexError:
        return None

def get_nearest_city ( lat , lng ) : qs = Location . objects . filter ( latitude__gte = lat - 1 , latitude__lte = lat + 1 , longitude__gte = lng - 1 , longitude__lte = lng + 1 ) try : return qs . order_by ( '-population' ) [ 0 ] except IndexError : return None


We download a list of the most often followed location . We can narrow the list to a certain country to do so we first type in the country and its capital city . it returns a LIST not a QuerySet!

def get_most_followed(country_code=None, limit=20):
    """
    We download a list of the most often followed location. We can narrow
    the list to a certain country, to do so, we first type in the country
    and its capital city. it returns a LIST, not a QuerySet!
    """
    qs = Location.objects
    kinds = ['PPLC', 'country',]
    if country_code is None:
        return list(qs.all().order_by('users')[:limit])
    main = list(qs.filter(country_code=country_code,
                  kind__in=kinds).order_by('kind'))
    full = list(qs.annotate(num_users=Count('users'))\
                    .filter(country_code=country_code)\
                    .exclude(kind__in=kinds)\
                    .order_by('-num_users')[:limit-len(main)])
    return main + full

def get_most_followed ( country_code = None , limit = 20 ) : qs = Location . objects kinds = [ 'PPLC' , 'country' , ] if country_code is None : return list ( qs . all ( ) . order_by ( 'users' ) [ : limit ] ) main = list ( qs . filter ( country_code = country_code , kind__in = kinds ) . order_by ( 'kind' ) ) full = list ( qs . annotate ( num_users = Count ( 'users' ) ) . filter ( country_code = country_code ) . exclude ( kind__in = kinds ) . order_by ( '-num_users' ) [ : limit - len ( main ) ] ) return main + full


This method helps us move contents between locations mainly if we want to delete one location but save contents in other one . It takes two location instances as arguments and move content from first to second of them .

def move_location_contents(old_location, new_location):
    """
    This method helps us move contents between locations, mainly, if we want
    to delete one location but save contents in other one. It takes two location
    instances as arguments and move content from first to second of them.
    """
    content_sets = ['news_set', 'poll_set', 'idea_set',
                    'discussion_set', 'pictures', 'projects',]
    # Get all 'standard' contents from first location and move to second one
    for content_type in content_sets:
        for item in getattr(old_location, content_type).all():
            item.location = new_location
            item.save()
    # Find all old location followers and make them follow new place
    for user in old_location.users.all():
        unfollow(user, old_location)
        if not user in new_location.users.all():
            follow(user, new_location, send_action=False)
            new_location.users.add(user)
    # Find all actions where old location acts as target and bind to new location.
    # This is not really good idea, but I hope it will be sufficient.
    actions = Action.objects.filter(target_object_id=old_location.pk,
        target_content_type=ContentType.objects.get_for_model(Location))
    for action in actions:
        action.target_object_id = new_location.pk
        action.save()


Helper that returns list of all followers from location with given ID . If deep is set to True list includes also followers of child locations .

def get_followers_from_location(location_pk, deep=False):
    """
    Helper that returns list of all followers from location with given ID.
    If `deep` is set to True, list includes also followers of child locations.
    """
    location = Location.objects.get(pk=location_pk)
    followers = list(location.users.all())
    if not deep:
        return followers
    for pk in location.get_children_id_list():
        location = Location.objects.get(pk=pk)
        for user in location.users.all():
            if not user in followers:
                followers.append(user)
    return followers

def get_followers_from_location ( location_pk , deep = False ) : location = Location . objects . get ( pk = location_pk ) followers = list ( location . users . all ( ) ) if not deep : return followers for pk in location . get_children_id_list ( ) : location = Location . objects . get ( pk = pk ) for user in location . users . all ( ) : if not user in followers : followers . append ( user ) return followers


A helper that changes various types of content into a unified format that will help us show them in templates . Works as a simple serializer . * deprecated * - it s much better to use activities app .

def obj_to_dict(obj):
    """
    A helper that changes various types of content into a unified format,
    that will help us show them in templates. Works as a simple serializer.
    *deprecated* - it's much better to use activities app.
    """
    content_type = ContentType.objects.get_for_model(obj)

    context = {
        'type': content_type.model,
        'name': capfirst(_(content_type.model)),
        'slug': obj.slug,
        'ct': content_type.pk,
        'pk': obj.pk,
        'url': obj.get_absolute_url(),
        'title': obj.__unicode__(),
        'image': obj.image_url,
        'thumbnail': obj.thumbnail,
        'retina_thumbnail': False,
        'location': obj.location.__unicode__(),
        'meta': {},
        'date_created': obj.date_created.isoformat(),
        'creator': {
            'id': obj.creator.pk,
            'url': obj.creator.profile.get_absolute_url(),
            'img': obj.creator.profile.avatar.url,
            'name': obj.creator.get_full_name(),
        },
    }

    if hasattr(obj,
               'category') and obj.category is not None and obj.category.pk:
        context.update({
            'category':
            {'pk': obj.category.pk,
             'name': obj.category.__unicode__(), }
        })

    if hasattr(obj, 'retina_thumbnail') and not obj.has_default_image:
        context['retina_thumbnail'] = obj.retina_thumbnail

    if hasattr(obj, 'has_default_image'):
        context['default_image'] = obj.has_default_image

    if content_type.model == 'idea':
        context.update({
            'description': obj.description,
            'meta': {'votes': obj.get_votes(), }
        })

    elif content_type.model == 'poll':
        context.update({'description': obj.question})

    elif content_type.model == 'news':
        context.update({'description': obj.content})

    elif content_type.model == 'discussion':
        context.update({
            'description': obj.intro,
            'meta': {'answers': obj.entry_set.count(), }
        })

    elif content_type.model == 'socialproject':
        context['description'] = obj.get_description()
        context['name'] = _(u"Project")

    else:
        raise Exception(_(u"Wrong model instance"))
    context['description'] = truncatewords_html(context['description'], 15)
    return context

def
obj_to_dict
(
obj
)
:
content_type
=
ContentType
.
objects
.
get_for_model
(
obj
)
context
=
{
'type'
:
content_type
.
model
,
'name'
:
capfirst
(
_
(
content_type
.
model
)
)
,
'slug'
:
obj
.
slug
,
'ct'
:
content_type
.
pk
,
'pk'
:
obj
.
pk
,
'url'
:
obj
.
get_absolute_url
(
)
,
'title'
:
obj
.
__unicode__
(
)
,
'image'
:
obj
.
image_url
,
'thumbnail'
:
obj
.
thumbnail
,
'retina_thumbnail'
:
False
,
'location'
:
obj
.
location
.
__unicode__
(
)
,
'meta'
:
{
}
,
'date_created'
:
obj
.
date_created
.
isoformat
(
)
,
'creator'
:
{
'id'
:
obj
.
creator
.
pk
,
'url'
:
obj
.
creator
.
profile
.
get_absolute_url
(
)
,
'img'
:
obj
.
creator
.
profile
.
avatar
.
url
,
'name'
:
obj
.
creator
.
get_full_name
(
)
,
}
,
}
if
hasattr
(
obj
,
'category'
)
and
obj
.
category
is
not
and
obj
.
category
.
pk
:
context
.
update
(
{
'category'
:
{
'pk'
:
obj
.
category
.
pk
,
'name'
:
obj
.
category
.
__unicode__
(
)
,
}
}
)
if
hasattr
(
obj
,
'retina_thumbnail'
)
and
not
obj
.
has_default_image
:
context
[
'retina_thumbnail'
]
=
obj
.
retina_thumbnail
if
hasattr
(
obj
,
'has_default_image'
)
:
context
[
'default_image'
]
=
obj
.
has_default_image
if
content_type
.
model
==
'idea'
:
context
.
update
(
{
'description'
:
obj
.
description
,
'meta'
:
{
'votes'
:
obj
.
get_votes
(
)
,
}
}
)
elif
content_type
.
model
==
'poll'
:
context
.
update
(
{
'description'
:
obj
.
question
}
)
elif
content_type
.
model
==
'news'
:
context
.
update
(
{
'description'
:
obj
.
content
}
)
elif
content_type
.
model
==
'discussion'
:
context
.
update
(
{
'description'
:
obj
.
intro
,
'meta'
:
{
'answers'
:
obj
.
entry_set
.
count
(
)
,
}
}
)
elif
content_type
.
model
==
'socialproject'
:
context
[
'description'
]
=
obj
.
get_description
(
)
context
[
'name'
]
=
_
(
u"Project"
)
else
:
raise
Exception
(
_
(
u"Wrong model instance"
)
)
context
[
'description'
]
=
truncatewords_html
(
context
[
'description'
]
,
15
)
return
context


Returns approximated percentage value given total and subset count .

def get_ptr(val, total):
    """ Returns approximated percentage value given total and subset count.
    """
    return int(float(val)/float(total)*100)

def get_ptr ( val , total ) : return int ( float ( val ) / float ( total ) * 100 )


Filter action queryset on daily basis . Pass qs to filter and current time to compare to . It returns number or None if count is 0 .

def qs_by_time(qs, current):
    """ Filter action queryset on daily basis. Pass qs to filter and current
        time to compare to. It returns number or None if count is 0.
    """
    qs = qs.filter(timestamp__year=current.year,
                   timestamp__month=current.month,
                   timestamp__day=current.day).count()
    return qs if qs > 0 else None

def qs_by_time ( qs , current ) : qs = qs . filter ( timestamp__year = current . year , timestamp__month = current . month , timestamp__day = current . day ) . count ( ) return qs if qs > 0 else None


Pie chart presenting content type items published in selected location . Data is prepared to be presented as pie chart with percentage values .

def pie_chart(location):
    """ Pie chart presenting content type items published in selected location.
        Data is prepared to be presented as pie chart, with percentage values.
    """
    ideas = location.idea_set.count()
    polls = location.poll_set.count()
    news = location.news_set.count()
    discussions = location.discussion_set.count()
    projects = location.projects.count()
    total = sum([ideas, polls, discussions, projects, ])

    return json.dumps({
        'title': location.__unicode__(),
        'subtitle': _(u"Published content summary"),
        'name': _(u"Published items"),
        'series': {
            (_(u'ideas'), get_ptr(ideas, total), ),
            (_(u'polls'), get_ptr(polls, total), ),
            (_(u'news'), get_ptr(news, total), ),
            (_(u'discussions'), get_ptr(discussions, total), ),
            (_(u'projects'), get_ptr(projects, total), ),
        },
    }, cls=SetEncoder)

def
pie_chart
(
location
)
:
ideas
=
location
.
idea_set
.
count
(
)
polls
=
location
.
poll_set
.
count
(
)
news
=
location
.
news_set
.
count
(
)
discussions
=
location
.
discussion_set
.
count
(
)
projects
=
location
.
projects
.
count
(
)
total
=
sum
(
[
ideas
,
polls
,
discussions
,
projects
,
]
)
return
json
.
dumps
(
{
'title'
:
location
.
__unicode__
(
)
,
'subtitle'
:
_
(
u"Published content summary"
)
,
'name'
:
_
(
u"Published items"
)
,
'series'
:
{
(
_
(
u'ideas'
)
,
get_ptr
(
ideas
,
total
)
,
)
,
(
_
(
u'polls'
)
,
get_ptr
(
polls
,
total
)
,
)
,
(
_
(
u'news'
)
,
get_ptr
(
news
,
total
)
,
)
,
(
_
(
u'discussions'
)
,
get_ptr
(
discussions
,
total
)
,
)
,
(
_
(
u'projects'
)
,
get_ptr
(
projects
,
total
)
,
)
,
}
,
}
,
cls
=
SetEncoder
)


Summary of different kinds of actions related to particular location .

def actions_chart(location):
    """ Summary of different kinds of actions related to particular location.
    """
    content_items = ['ideas', 'polls', 'news', 'discussions', 'projects', ]

    content_types = {
        'ideas': ContentType.objects.get(app_label='ideas', model='idea'),
        'polls': ContentType.objects.get(app_label='polls', model='poll'),
        'news': ContentType.objects.get(app_label='blog', model='news'),
        'discussions': ContentType.objects.get(app_label='topics', model='discussion'),
        'projects': ContentType.objects.get(app_label='projects', model='socialproject'),
    }

    stream = target_stream(location)

    started = stream.last().timestamp
    current = started
    maximum = timezone.now() + datetime.timedelta(hours=12)

    labels = {
        'ideas': _(u"ideas"),
        'polls': _(u"polls"),
        'news': _(u"news"),
        'discussions': _(u"discussions"),
        'projects': _(u"projects"),
    }

    counters = {
        'ideas': [],
        'polls': [],
        'news': [],
        'discussions': [],
        'projects': [],
    }

    while current < maximum:
        for itm in content_items:
            counters[itm].append(qs_by_time(stream.filter(
                action_object_content_type=content_types[itm]), current))
        current += datetime.timedelta(days=1)

    return json.dumps({
        'title': location.__unicode__(),
        'subtitle': _(u"Activity summary"),
        'started': str(started),
        'labels': labels,
        'series': counters, })

def
actions_chart
(
location
)
:
content_items
=
[
'ideas'
,
'polls'
,
'news'
,
'discussions'
,
'projects'
,
]
content_types
=
{
'ideas'
:
ContentType
.
objects
.
get
(
app_label
=
'ideas'
,
model
=
'idea'
)
,
'polls'
:
ContentType
.
objects
.
get
(
app_label
=
'polls'
,
model
=
'poll'
)
,
'news'
:
ContentType
.
objects
.
get
(
app_label
=
'blog'
,
model
=
'news'
)
,
'discussions'
:
ContentType
.
objects
.
get
(
app_label
=
'topics'
,
model
=
'discussion'
)
,
'projects'
:
ContentType
.
objects
.
get
(
app_label
=
'projects'
,
model
=
'socialproject'
)
,
}
stream
=
target_stream
(
location
)
started
=
stream
.
last
(
)
.
timestamp
current
=
started
maximum
=
timezone
.
now
(
)
+
datetime
.
timedelta
(
hours
=
12
)
labels
=
{
'ideas'
:
_
(
u"ideas"
)
,
'polls'
:
_
(
u"polls"
)
,
'news'
:
_
(
u"news"
)
,
'discussions'
:
_
(
u"discussions"
)
,
'projects'
:
_
(
u"projects"
)
,
}
counters
=
{
'ideas'
:
[
]
,
'polls'
:
[
]
,
'news'
:
[
]
,
'discussions'
:
[
]
,
'projects'
:
[
]
,
}
while
current
<
maximum
:
for
itm
in
content_items
:
counters
[
itm
]
.
append
(
qs_by_time
(
stream
.
filter
(
action_object_content_type
=
content_types
[
itm
]
)
,
current
)
)
current
+=
datetime
.
timedelta
(
days
=
1
)
return
json
.
dumps
(
{
'title'
:
location
.
__unicode__
(
)
,
'subtitle'
:
_
(
u"Activity summary"
)
,
'started'
:
str
(
started
)
,
'labels'
:
labels
,
'series'
:
counters
,
}
)


Presents timeline data containing target location followers .

def follow_chart(location):
    """ Presents timeline data containing target location followers.
    """
    qs = Follow.objects.filter(object_id=location.pk,
            content_type=ContentType.objects.get_for_model(location))

    started = location.date_created
    current = started
    maximum = timezone.now() + datetime.timedelta(hours=12)
    prev_qs = 0

    followers = []
    while current < maximum:
        fqs = qs.filter(started__year=current.year,
                        started__month=current.month,
                        started__day=current.day).count()
        prev_qs += fqs
        followers.append(prev_qs)
        current += datetime.timedelta(days=1)

    return json.dumps({
        'title': location.__unicode__(),
        'subtitle': _(u"followers activity"),
        'name': _(u"followers"),
        'started': str(started),
        'series': followers, })

def
follow_chart
(
location
)
:
qs
=
Follow
.
objects
.
filter
(
object_id
=
location
.
pk
,
content_type
=
ContentType
.
objects
.
get_for_model
(
location
)
)
started
=
location
.
date_created
current
=
started
maximum
=
timezone
.
now
(
)
+
datetime
.
timedelta
(
hours
=
12
)
prev_qs
=
0
followers
=
[
]
while
current
<
maximum
:
fqs
=
qs
.
filter
(
started__year
=
current
.
year
,
started__month
=
current
.
month
,
started__day
=
current
.
day
)
.
count
(
)
prev_qs
+=
fqs
followers
.
append
(
prev_qs
)
current
+=
datetime
.
timedelta
(
days
=
1
)
return
json
.
dumps
(
{
'title'
:
location
.
__unicode__
(
)
,
'subtitle'
:
_
(
u"followers activity"
)
,
'name'
:
_
(
u"followers"
)
,
'started'
:
str
(
started
)
,
'series'
:
followers
,
}
)


Get data to use in map inputs - set initial center location and zoom . This values depends on location s kind and size .

def current_location_data(context):
    """ Get data to use in map inputs - set initial center location and zoom.
        This values depends on location's kind and size.
    """
    location = context.get('location')
    if location is None:
        return JSONRenderer().render({})
    s = LocationMapDataSerializer(location)
    return JSONRenderer().render(s.data)

def current_location_data ( context ) : location = context . get ( 'location' ) if location is None : return JSONRenderer ( ) . render ( { } ) s = LocationMapDataSerializer ( location ) return JSONRenderer ( ) . render ( s . data )


Alerts Google that the sitemap for the current site has been updated . If sitemap_url is provided it should be an absolute path to the sitemap for this site -- e . g . / sitemap . xml . If sitemap_url is not provided this function will attempt to deduce it by using urlresolvers . reverse () .

def ping_google(sitemap_url=None, ping_url=PING_URL):
    """
    Alerts Google that the sitemap for the current site has been updated.
    If sitemap_url is provided, it should be an absolute path to the sitemap
    for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this
    function will attempt to deduce it by using urlresolvers.reverse().
    """
    if sitemap_url is None:
        try:
            # First, try to get the "index" sitemap URL.
            sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.index')
        except urlresolvers.NoReverseMatch:
            try:
                # Next, try for the "global" sitemap URL.
                sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap')
            except urlresolvers.NoReverseMatch:
                pass

    if sitemap_url is None:
        raise SitemapNotFound("You didn't provide a sitemap_url, and the sitemap URL couldn't be auto-detected.")

    if not django_apps.is_installed('django.contrib.sites'):
        raise ImproperlyConfigured("ping_google requires django.contrib.sites, which isn't installed.")
    Site = django_apps.get_model('sites.Site')
    current_site = Site.objects.get_current()
    url = "http://%s%s" % (current_site.domain, sitemap_url)
    params = urlencode({'sitemap': url})
    urlopen("%s?%s" % (ping_url, params))


Searches through a folder in order to find static pages .

def get_all_pages(self):
        """
        Searches through a folder in order to find static pages.
        """
        pages = []
        for page in os.listdir(PAGE_DIR):
            pages.append({
                'url': str(reverse('pages:page', kwargs={'page': page[:4]})),
                'name': page[:4],
            })
        return pages

def get_all_pages ( self ) : pages = [ ] for page in os . listdir ( PAGE_DIR ) : pages . append ( { 'url' : str ( reverse ( 'pages:page' , kwargs = { 'page' : page [ : 4 ] } ) ) , 'name' : page [ : 4 ] , } ) return pages


Function takes one line of file and creates Country model .

def import_country(entry):
    """ Function takes one line of file and creates Country model. """
    if entry.startswith('#'):
        return False
    entry = entry.split('\t')

    # Incomplete entries are not desired
    if not entry[16] or entry[16] == ' ': return False

    try:
        chk = CountryInfo.objects.get(pk=int(entry[16]))
        # Entry exists. Skipping.
        logging.info("Country already exists: %s. Skipping",
                     unicode(entry[4]).encode('utf-8'))
        return True
    except CountryInfo.DoesNotExist:
        pass

    try:
        country = CountryInfo.objects.create(
            id          = int(entry[16]),
            iso_alpha2  = entry[0],
            iso_alpha3  = entry[1],
            iso_numeric = entry[2],
            code        = entry[3],
            name        = entry[4],
            capital     = entry[5],
            area        = float(entry[6]) if entry[6] else 0.0,
            population  = int(entry[7]) if entry[7] else 0,
            continent   = entry[8],
            languages   = entry[15]
        )

        country.save()

        logging.info("Country saved: %s",
                     unicode(entry[4]).encode('utf-8'))
    except Exception as ex:
        logging.error("Error importing country: %s - %s",
                      unicode(entry[4]).encode('utf-8'), ex.strerror)

def
import_country
(
entry
)
:
if
entry
.
startswith
(
'#'
)
:
return
False
entry
=
entry
.
split
(
'\t'
)
# Incomplete entries are not desired
if
not
entry
[
16
]
or
entry
[
16
]
==
' '
:
return
False
try
:
chk
=
CountryInfo
.
objects
.
get
(
pk
=
int
(
entry
[
16
]
)
)
# Entry exists. Skipping.
logging
.
info
(
"Country already exists: %s. Skipping"
,
unicode
(
entry
[
4
]
)
.
encode
(
'utf-8'
)
)
return
True
except
CountryInfo
.
DoesNotExist
:
pass
try
:
country
=
CountryInfo
.
objects
.
create
(
id
=
int
(
entry
[
16
]
)
,
iso_alpha2
=
entry
[
0
]
,
iso_alpha3
=
entry
[
1
]
,
iso_numeric
=
entry
[
2
]
,
code
=
entry
[
3
]
,
name
=
entry
[
4
]
,
capital
=
entry
[
5
]
,
area
=
float
(
entry
[
6
]
)
if
entry
[
6
]
else
0.0
,
population
=
int
(
entry
[
7
]
)
if
entry
[
7
]
else
0
,
continent
=
entry
[
8
]
,
languages
=
entry
[
15
]
)
country
.
save
(
)
logging
.
info
(
"Country saved: %s"
,
unicode
(
entry
[
4
]
)
.
encode
(
'utf-8'
)
)
except
Exception
as
ex
:
logging
.
error
(
"Error importing country: %s - %s"
,
unicode
(
entry
[
4
]
)
.
encode
(
'utf-8'
)
,
ex
.
strerror
)


Function takes single line of input file and creates GeoName instance .

def import_geoname(entry):
    """ Function takes single line of input file and creates GeoName instance. """
    if entry.startswith('#'):
        return False
    entry = entry.split('\t')

    # Incomplete entries are not desired
    if not entry[0] or entry[0] == ' ': return False

    try:
        chk = GeoName.objects.get(pk=int(entry[0]))
        # Entry exists. Skipping.
        logging.info("GeoName object already exists: %s. Skipping", entry[0])
        return True
    except GeoName.DoesNotExist:
        pass

    try:
        geoname = GeoName.objects.create(
            id        = int(entry[0]),
            name      = entry[1],
            name_std  = entry[2],
            latitude  = float(entry[4]) if entry[4] else 0.0,
            longitude = float(entry[5]) if entry[4] else 0.0,
            feature_class = entry[6],
            feature_code  = entry[7],
            country = entry[8],
            admin1  = entry[10],
            admin2  = entry[11],
            admin3  = entry[12],
            admin4  = entry[13],
            population = int(entry[14]) if entry[14] else 0,
        )

        geoname.save()

        logging.info("GeoName object saved: %s", unicode(entry[1]).encode('utf-8'))
    except Exception as ex:
        logging.error("Error importing GeoName: %s - %s", entry[0], repr(ex))


Function takes single line from admin1CodesASCII . txt file and creates admin code model in database .

def import_admin_code(entry):
    """
    Function takes single line from admin1CodesASCII.txt file and creates
    admin code model in database.
    """
    if entry.startswith('#'):
        return False
    entry = entry.split('\t')

    # Incomplete entries are not desired
    if not entry[0] or entry[0] == ' ': return False

    try:
        chk = AdminCode.objects.get(pk=int(entry[3]))
        # Entry exists. Skipping.
        logging.info("Admin code already exists: %s. Skipping",
                     entry[3].replace('\n', ''))
        return True
    except AdminCode.DoesNotExist:
        pass

    try:
        admcode = AdminCode.objects.create(
            id       = int(entry[3]),
            name     = entry[1],
            name_std = entry[2],
            country  = entry[0].split('.')[0],
            code     = entry[0].split('.')[1]
        )

        admcode.save()

        logging.info("Admin code object saved: %s", entry[3].replace('\n', ''))
    except Exception as ex:
        logging.error("Error importing Admin code: %s - %s",
                      entry[3].replace('\n', ''), repr(ex))


Takes one line of input file and returns dictionary .

def import_alt_name(entry):
    """ Takes one line of input file and returns dictionary. """
    if entry.startswith('#'):
        return False
    entry = entry.split('\t')

    # We're interested only in 1st group langs
    if len(entry[2]) != 2: return None
    # ... and objects we are really going to use
    target = None
    try:
        target = CountryInfo.objects.get(pk=int(entry[1]))
    except CountryInfo.DoesNotExist:
        target = None
    try:
        target = AdminCode.objects.get(pk=int(entry[1]))
    except AdminCode.DoesNotExist:
        target = None
    try:
        target = GeoName.objects.get(pk=int(entry[1]))
    except GeoName.DoesNotExist:
        target = None
    if target is None:
        logging.info("No geo entry for alternate name. Skipping")
        return True

    try:
        chk = AltName.objects.get(pk=int(entry[0]))
        # Entry exists. Skipping.
        logging.info("Alternate name already exists: %s. Skipping",
                     unicode(entry[3]).encode('utf-8'))
        return True
    except AltName.DoesNotExist:
        pass

    try:
        alt_name = AltName.objects.create(
            id            = int(entry[0]),
            geonameid     = int(entry[1]),
            language      = entry[2],
            altername     = unicode(entry[3]),
            is_preferred  = bool(entry[4]),
            is_short      = bool(entry[5]),
            is_historic   = bool(entry[6]),
            is_colloquial = bool(entry[7]),
        )

        alt_name.save()

        logging.info("Alternate name object saved: %s",
                             unicode(entry[3]).encode('utf-8'))
    except Exception as ex:
        logging.error("Error importing Alternate name: %s - %s",
                      unicode(entry[3]).encode('utf-8'), repr(ex))


Notify newss author about that his news was deleted .

def notify_about_news_deletion(sender, instance, **kwargs):
    """ Notify newss author about that his news was deleted. """
    # For now we assume that only superuser could delete news entries.
    admin = User.objects.filter(is_superuser=True)[0]
    notify(admin, instance.creator,
        key="deletion",
        verb="deleted your blog entry",
        action_object=instance
    )


Check if gallery folder exists and create new one if not .

def create_gallery(gallery_name):
    """
    Check if gallery folder exists and create new one if not.
    """
    filepath = os.path.join(settings.MEDIA_ROOT, gallery_name)
    thumb_path = os.path.join(filepath, 'thumbs')
    if not os.path.exists(filepath):
        try:
            os.makedirs(os.path.join(filepath, 'thumbs'))
            return True
        except IOError:
            return False
    return True

def create_gallery ( gallery_name ) : filepath = os . path . join ( settings . MEDIA_ROOT , gallery_name ) thumb_path = os . path . join ( filepath , 'thumbs' ) if not os . path . exists ( filepath ) : try : os . makedirs ( os . path . join ( filepath , 'thumbs' ) ) return True except IOError : return False return True


Create thumbnail for given image in selected gallery .

def create_gallery_thumbnail(gallery, filename):
    """
    Create thumbnail for given image in selected gallery.
    @param gallery  (string) Username or place slug
    @param filename (string) Image filename
    """
    filepath = os.path.join(settings.MEDIA_ROOT, gallery)
    thumb_path = filepath + '/thumbs/'

    for w, h in settings.THUMB_SIZES:
        size = w, h
        thumbfile = str(w) + 'x' + str(h) + '_' + filename
        thumbname = os.path.join(thumb_path + thumbfile)
        try:
            thumb = Image.open(filepath + '/' + filename)
            thumb.thumbnail(size, Image.ANTIALIAS)
            thumb.save(thumbname, 'JPEG')
        except IOError:
            return False
    return True

def create_gallery_thumbnail ( gallery , filename ) : filepath = os . path . join ( settings . MEDIA_ROOT , gallery ) thumb_path = filepath + '/thumbs/' for w , h in settings . THUMB_SIZES : size = w , h thumbfile = str ( w ) + 'x' + str ( h ) + '_' + filename thumbname = os . path . join ( thumb_path + thumbfile ) try : thumb = Image . open ( filepath + '/' + filename ) thumb . thumbnail ( size , Image . ANTIALIAS ) thumb . save ( thumbname , 'JPEG' ) except IOError : return False return True


Creates name based on md5 sum of current date and time to avoid naming conflicts in files .

def gallery_item_name():
    """
    Creates name based on md5 sum of current date and time to avoid naming
    conflicts in files.
    """
    rand = random.randint(0, 10000)
    basename = hashlib.md5()
    basename.update(str(datetime.now().time) + str(rand))
    return basename.hexdigest() + '.jpg'

def gallery_item_name ( ) : rand = random . randint ( 0 , 10000 ) basename = hashlib . md5 ( ) basename . update ( str ( datetime . now ( ) . time ) + str ( rand ) ) return basename . hexdigest ( ) + '.jpg'


A view that allows to delete images from the gallery . The pk parameter is compulsory and when it is empty an error will occur . The slug parameter is here only to match the view in urlconf with the locations application .

def location_gallery_delete(request, slug=None, pk=None):
    """
    A view that allows to delete images from the gallery. The 'pk' parameter is
    compulsory and when it is empty, an error will occur. The 'slug' parameter
    is here only to match the view in urlconf with the 'locations' application.
    """
    item = get_object_or_404(LocationGalleryItem, pk=pk)
    if request.user.is_superuser or is_moderator(request.user, item.location):
        item.delete()
        return redirect(
            reverse('locations:gallery',
            kwargs={'location_slug':item.location.slug})
        )
    else:
        return HttpResponseForbidden()

def location_gallery_delete ( request , slug = None , pk = None ) : item = get_object_or_404 ( LocationGalleryItem , pk = pk ) if request . user . is_superuser or is_moderator ( request . user , item . location ) : item . delete ( ) return redirect ( reverse ( 'locations:gallery' , kwargs = { 'location_slug' : item . location . slug } ) ) else : return HttpResponseForbidden ( )


def post(self, request, pk):
        """
        Save changes in image.
        """
        x = request.POST.get('x')
        y = request.POST.get('y')
        x2 = request.POST.get('x2')
        y2 = request.POST.get('y2')
        item = get_object_or_404(UserGalleryItem, pk=pk)
        filename = item.picture_name
        filepath = item.get_filepath()
        file = os.path.join(filepath, filename)
        box = (int(x), int(y), int(x2), int(y2))

        img = Image.open(file)
        img.crop(box).save(file)
        create_gallery_thumbnail(request.user.username, filename)

        return redirect(reverse('gallery:index'))

def post ( self , request , pk ) : x = request . POST . get ( 'x' ) y = request . POST . get ( 'y' ) x2 = request . POST . get ( 'x2' ) y2 = request . POST . get ( 'y2' ) item = get_object_or_404 ( UserGalleryItem , pk = pk ) filename = item . picture_name filepath = item . get_filepath ( ) file = os . path . join ( filepath , filename ) box = ( int ( x ) , int ( y ) , int ( x2 ) , int ( y2 ) ) img = Image . open ( file ) img . crop ( box ) . save ( file ) create_gallery_thumbnail ( request . user . username , filename ) return redirect ( reverse ( 'gallery:index' ) )


Send action about new gallery . Takes ContentObjectGallery as argument .

def created_gallery(user, instance):
    """ Send action about new gallery. Takes ContentObjectGallery as argument.
    """
    verb = _(u"created gallery")
    publisher = instance.published_in
    if publisher is None:
        action.send(user, verb=verb, action_object=instance)
    action.send(user, verb=verb, action_object=instance, target=publisher)
    if hasattr(publisher, 'creator'):
        target_user = publisher.creator
    elif hasattr(publisher, 'author'):
        target_user = publisher.author
    if target_user == user:
        return True
    notify(user, target_user,
           verb=verb,
           key="gallery",
           action_object=instance,
           action_target=publisher)

def
created_gallery
(
user
,
instance
)
:
verb
=
_
(
u"created gallery"
)
publisher
=
instance
.
published_in
if
publisher
is
:
action
.
send
(
user
,
verb
=
verb
,
action_object
=
instance
)
action
.
send
(
user
,
verb
=
verb
,
action_object
=
instance
,
target
=
publisher
)
if
hasattr
(
publisher
,
'creator'
)
:
target_user
=
publisher
.
creator
elif
hasattr
(
publisher
,
'author'
)
:
target_user
=
publisher
.
author
if
target_user
==
user
:
return
True
notify
(
user
,
target_user
,
verb
=
verb
,
key
=
"gallery"
,
action_object
=
instance
,
action_target
=
publisher
)


Send information about new picture in existing gallery .

def uploaded_picture(instance):
    """ Send information about new picture in existing gallery.
    """
    verb = _(u"uploaded picture")
    action.send(instance.uploaded_by,
                verb=verb,
                action_object=instance,
                target=instance.gallery)

def
uploaded_picture
(
instance
)
:
verb
=
_
(
u"uploaded picture"
)
action
.
send
(
instance
.
uploaded_by
,
verb
=
verb
,
action_object
=
instance
,
target
=
instance
.
gallery
)


Make sure that all files will be deleted along with gallery itself .

def cleanup_gallery(sender, instance, **kwargs):
    """ Make sure that all files will be deleted along with gallery itself.
    """
    rmdir(instance)

def cleanup_gallery ( sender , instance , * * kwargs ) : rmdir ( instance )


Remove all images when model is deleted .

def cleanup_image(sender, instance, **kwargs):
    """ Remove all images when model is deleted.
    """
    massrm(instance)

def cleanup_image ( sender , instance , * * kwargs ) : massrm ( instance )


def adjust_images(sender, instance, **kwargs):
    """ Crop image.
    """
    generate_thumbs(instance.image.path)

def adjust_images ( sender , instance , * * kwargs ) : generate_thumbs ( instance . image . path )


The function takes an absolute system path to the background image ( mainly with location and users in mind ) and adds / changes the name for the cropped file ( prefix ) . The prefix can be set in any way but only s_ will work later on in the templates .

def rename_background_file(filepath, pref="s_"):
    """
    The function takes an absolute system path to the background image (mainly
    with location and users in mind) and adds/changes the name for the cropped
    file (prefix). The prefix can be set in any way, but only "s_" will work
    later on in the templates.

    TODO: global cropped image prefix.
    """
    path, file = os.path.split(filepath)
    return os.path.join(path, pref + file)

def rename_background_file ( filepath , pref = "s_" ) : path , file = os . path . split ( filepath ) return os . path . join ( path , pref + file )


A function that allows to change the images before they get uploaded and send to Django enginge . Used while uploading background images and avatars to create temporary files that can be used in ImageField model of Django .

def handle_tmp_image(image):
    """
    A function that allows to "change" the images before they get uploaded and send
    to Django enginge. Used while uploading background images and avatars to create
    temporary files that can be used in ImageField model of Django.
    """
    img_io = StringIO.StringIO()
    image.save(img_io, format='JPEG')
    return InMemoryUploadedFile(img_io, None, 'foo.jpg', 'image/jpeg',
                                    img_io.len, None)

def handle_tmp_image ( image ) : img_io = StringIO . StringIO ( ) image . save ( img_io , format = 'JPEG' ) return InMemoryUploadedFile ( img_io , None , 'foo.jpg' , 'image/jpeg' , img_io . len , None )


The function take the PIL image as an argument and returns the same object but with changed dimensions . The change of dimensions takes place to the maximum width .

def resize_image(image, size=None):
    """
    The function take the PIL image as an argument and returns the same object
    but with changed dimensions. The change of dimensions takes place to the
    maximum width.
    """
    max_w, max_h = settings.BACKGROUND_IMAGE_SIZE if size is None else size
    width, height = image.getdata().size
    ratio = float(max_w) / float(width)
    return image.resize((max_w, int(height*ratio)), Image.ANTIALIAS)

def resize_image ( image , size = None ) : max_w , max_h = settings . BACKGROUND_IMAGE_SIZE if size is None else size width , height = image . getdata ( ) . size ratio = float ( max_w ) / float ( width ) return image . resize ( ( max_w , int ( height * ratio ) ) , Image . ANTIALIAS )


A simple function that silences errors while deleting files that don t exist .

def delete_image(imagepath):
    """
    A simple function that "silences" errors while deleting files that don't exist.
    """
    try:
        os.unlink(imagepath)
    except OSError, IOError:
        pass

def delete_image ( imagepath ) : try : os . unlink ( imagepath ) except OSError , IOError : pass


A Method that takes an instance of an object as an argument and returns the correct name of the filed that stores the background image . Works for UserProfile model and Location .

def get_fieldname(instance):
    """
    A Method that takes an instance of an object as an argument and returns the
    correct name of the filed that stores the background image. Works for UserProfile
    model and Location.
    """
    field_names = ('background_image', 'image')
    fieldname = None

    for fn in field_names:
        fieldname = instance.__dict__.get(fn)
        if fieldname is not None:
            break

    if fieldname is None:
        raise Exception("Wrong model instance")

    return fieldname

def
get_fieldname
(
instance
)
:
field_names
=
(
'background_image'
,
'image'
)
fieldname
=
for
fn
in
field_names
:
fieldname
=
instance
.
__dict__
.
get
(
fn
)
if
fieldname
is
not
:
break
if
fieldname
is
:
raise
Exception
(
"Wrong model instance"
)
return
fieldname


Crop background images and display them in thumbs . Both arguments are required . Image is PIL image instance ( resized and cropped to fit background dimmensions ) and pathname means upload path ( excluding MEDIA_ROOT e . g same as in model s field declaration ) .

def crop_background(image, pathname, max_size=(270,150)):
    """
    Crop background images and display them in thumbs. Both arguments are
    required. Image is PIL image instance (resized and cropped to fit background
    dimmensions) and pathname means upload path (excluding MEDIA_ROOT, e.g same
    as in model's field declaration).
    """
    max_w, max_h  = max_size
    width, height = image.getdata().size
    new_width     = int(width * float(max_h)/float(height))
    startx        = int((new_width - max_w) / 2)

    image = image.resize((new_width, max_h), Image.ANTIALIAS)
    box = (startx, 0, startx + max_w, max_h)
    image = image.crop(box)
    path = os.path.join(settings.MEDIA_ROOT, rename_background_file(pathname))
    image.save(path, 'JPEG')

def crop_background ( image , pathname , max_size = ( 270 , 150 ) ) : max_w , max_h = max_size width , height = image . getdata ( ) . size new_width = int ( width * float ( max_h ) / float ( height ) ) startx = int ( ( new_width - max_w ) / 2 ) image = image . resize ( ( new_width , max_h ) , Image . ANTIALIAS ) box = ( startx , 0 , startx + max_w , max_h ) image = image . crop ( box ) path = os . path . join ( settings . MEDIA_ROOT , rename_background_file ( pathname ) ) image . save ( path , 'JPEG' )


Resize background image to fit for sizes defined in settings file . Method takes model instance as argument and performs resizing and cropping .

def resize_background_image(sender, instance, created, **kwargs):
    """
    Resize background image to fit for sizes defined in settings file. Method
    takes model instance as argument and performs resizing and cropping.
    """
    fieldname = instance.image

    if u'nowhere.jpg' in fieldname.path or u'background.jpg' in fieldname.path or u'default.jpg' in fieldname.path:
        return False

    max_width, max_height = settings.BACKGROUND_IMAGE_SIZE
    im = ImageManager(fieldname.path, "/".join(fieldname.path.split('/')[:-1]))
    im.fixed_thumb(max_width, max_height)

def resize_background_image ( sender , instance , created , * * kwargs ) : fieldname = instance . image if u'nowhere.jpg' in fieldname . path or u'background.jpg' in fieldname . path or u'default.jpg' in fieldname . path : return False max_width , max_height = settings . BACKGROUND_IMAGE_SIZE im = ImageManager ( fieldname . path , "/" . join ( fieldname . path . split ( '/' ) [ : - 1 ] ) ) im . fixed_thumb ( max_width , max_height )


def delete_background_image(sender, instance, **kwargs):
    """
    A Method that deletes the background image for location and user profile models
    """
    fieldname = get_fieldname(instance)

    if u'nowhere.jpg' in fieldname or u'background.jpg' in fieldname:
        return False

    if (os.path.isfile(fieldname)):
        os.unlink(fieldname)

    path, fname = os.path.splitext(fieldname)
    fname = "s_" + str(fname)
    fpath = os.path.join(path, fname)

    if os.path.isfile(fpath):
        os.unlink(fpath)

def delete_background_image ( sender , instance , * * kwargs ) : fieldname = get_fieldname ( instance ) if u'nowhere.jpg' in fieldname or u'background.jpg' in fieldname : return False if ( os . path . isfile ( fieldname ) ) : os . unlink ( fieldname ) path , fname = os . path . splitext ( fieldname ) fname = "s_" + str ( fname ) fpath = os . path . join ( path , fname ) if os . path . isfile ( fpath ) : os . unlink ( fpath )


We crop the image to show it on the main site of the gallery .

def crop_gallery_thumb(sender, instance, **kwargs):
    """
    We crop the image to show it on the main site of the gallery.
    """
    filename = 'cropped_' + instance.picture_name
    if hasattr(instance, 'location'):
        path = os.path.join(settings.MEDIA_ROOT, instance.location.slug)
    else:
        path = os.path.join(settings.MEDIA_ROOT, instance.user.username)
    image = Image.open(instance.get_filename())
    max_w, max_h = settings.GALLERY_THUMB_SIZE
    width, height = image.getdata().size
    if height > width:
        ratio = float(max_w)/float(width)
        image = image.resize((max_w, int(height*ratio)), Image.ANTIALIAS)
        box = (0, 0, max_w, max_h)
    else:
        ratio = float(max_h)/float(height)
        new_width = int(width*ratio)
        image = image.resize((new_width, max_h), Image.ANTIALIAS)
        start_x = 0
        x_factor = max_w
        if new_width > max_w:
            start_x = int((float(new_width)-float(max_w))/2)
        if new_width < max_w:
            nratio = float(max_w)/float(new_width)
            cw, ch = image.getdata().size
            image = image.resize((max_w, int(float(ch)*nratio)), Image.ANTIALIAS)
        stop_x = start_x + x_factor
        box = (start_x, 0, stop_x, max_h)
    image = image.crop(box)
    image.save(os.path.join(path, filename), 'JPEG')

def crop_gallery_thumb ( sender , instance , * * kwargs ) : filename = 'cropped_' + instance . picture_name if hasattr ( instance , 'location' ) : path = os . path . join ( settings . MEDIA_ROOT , instance . location . slug ) else : path = os . path . join ( settings . MEDIA_ROOT , instance . user . username ) image = Image . open ( instance . get_filename ( ) ) max_w , max_h = settings . GALLERY_THUMB_SIZE width , height = image . getdata ( ) . size if height > width : ratio = float ( max_w ) / float ( width ) image = image . resize ( ( max_w , int ( height * ratio ) ) , Image . ANTIALIAS ) box = ( 0 , 0 , max_w , max_h ) else : ratio = float ( max_h ) / float ( height ) new_width = int ( width * ratio ) image = image . resize ( ( new_width , max_h ) , Image . ANTIALIAS ) start_x = 0 x_factor = max_w if new_width > max_w : start_x = int ( ( float ( new_width ) - float ( max_w ) ) / 2 ) if new_width < max_w : nratio = float ( max_w ) / float ( new_width ) cw , ch = image . getdata ( ) . size image = image . resize ( ( max_w , int ( float ( ch ) * nratio ) ) , Image . ANTIALIAS ) stop_x = start_x + x_factor box = ( start_x , 0 , stop_x , max_h ) image = image . crop ( box ) image . save ( os . path . join ( path , filename ) , 'JPEG' )


The signal that deletes the cropped image for gallery element .

def delete_cropped_thumb(sender, instance, **kwargs):
    """
    The signal that deletes the cropped image for gallery element.
    """
    filename = 'cropped_' + instance.picture_name
    if hasattr(instance, 'location'):
        filepath = os.path.join(settings.MEDIA_ROOT, instance.location.slug, filename)
    else:
        filepath = os.path.join(settings.MEDIA_ROOT, instance.user.username, filename)
    delete_image(filepath)

def delete_cropped_thumb ( sender , instance , * * kwargs ) : filename = 'cropped_' + instance . picture_name if hasattr ( instance , 'location' ) : filepath = os . path . join ( settings . MEDIA_ROOT , instance . location . slug , filename ) else : filepath = os . path . join ( settings . MEDIA_ROOT , instance . user . username , filename ) delete_image ( filepath )


Given file name or full path and size tuple returns thumbnail name .

def thumb_name(filename, size):
    """ Given file name or full path and size tuple returns thumbnail name. """
    file, ext = os.path.splitext(filename)
    return "%s_%dx%d%s" % (file, size[0], size[1], ext)

def thumb_name ( filename , size ) : file , ext = os . path . splitext ( filename ) return "%s_%dx%d%s" % ( file , size [ 0 ] , size [ 1 ] , ext )


The function takes the path to the image file as an argument and creates a minature with the given ( typed ) dimensions . The image will be shrunk and cropped intelligently .

def crop_thumb(filename, size):
    """
    The function takes the path to the image file as an argument and creates
    a minature with the given (typed) dimensions. The image will be shrunk and
    cropped "intelligently".
    """
    image = Image.open(filename)
    max_w, max_h = size
    width, height = image.getdata().size
    if height > width:
        ratio = float(max_w)/float(width)
        image = image.resize((max_w, int(height*ratio)), Image.ANTIALIAS)
        box = (0, 0, max_w, max_h)
    else:
        ratio = float(max_h)/float(height)
        new_width = int(width*ratio)
        image = image.resize((new_width, max_h), Image.ANTIALIAS)
        start_x = 0
        x_factor = max_w
        if new_width >= max_w:
            start_x = int((float(new_width)-float(max_w))/2)
        else:
            nratio = float(max_w)/float(new_width)
            cw, ch = image.getdata().size
            image = image.resize((max_w, int(float(ch)*nratio)), Image.ANTIALIAS)
        stop_x = start_x + x_factor
        box = (start_x, 0, stop_x, max_h)
    image = image.crop(box)
    image.save(thumb_name(filename, size), 'JPEG')

def crop_thumb ( filename , size ) : image = Image . open ( filename ) max_w , max_h = size width , height = image . getdata ( ) . size if height > width : ratio = float ( max_w ) / float ( width ) image = image . resize ( ( max_w , int ( height * ratio ) ) , Image . ANTIALIAS ) box = ( 0 , 0 , max_w , max_h ) else : ratio = float ( max_h ) / float ( height ) new_width = int ( width * ratio ) image = image . resize ( ( new_width , max_h ) , Image . ANTIALIAS ) start_x = 0 x_factor = max_w if new_width >= max_w : start_x = int ( ( float ( new_width ) - float ( max_w ) ) / 2 ) else : nratio = float ( max_w ) / float ( new_width ) cw , ch = image . getdata ( ) . size image = image . resize ( ( max_w , int ( float ( ch ) * nratio ) ) , Image . ANTIALIAS ) stop_x = start_x + x_factor box = ( start_x , 0 , stop_x , max_h ) image = image . crop ( box ) image . save ( thumb_name ( filename , size ) , 'JPEG' )


A small helper . We give the path to the image and the function returns a tuplet with its height and width in pixels . We return the sizes of the images already matched ( changed ) .

def get_image_size(imagepath):
    """
    A small helper. We give the path to the image and the function returns
    a tuplet with its height and width in pixels. We return the sizes of
    the images already matched (changed).
    """
    try:
        image = Image.open(os.path.splitext(imagepath)[0] + '_fx.jpg')
        return image.getdata().size
    except IOError:
        # Element najwyraźniej ma ustawiony obrazek domyślny
        return 0


A unified method that manages images for our model ImagableItemMixin . Readies images of standarized sizes and the same for retina . The size of the image is set in settings . DEFAULT_IMG_SIZE . We preserve the original .

def adjust_uploaded_image(sender, instance, **kwargs):
    """
    A unified method that manages images for our model ImagableItemMixin.
    Readies images of standarized sizes and the same for retina.
    The size of the image is set in settings.DEFAULT_IMG_SIZE. We preserve
    the original.
    """
    # Ignoruj wpisy z domyślnymi obrazami
    if instance.image.name == settings.DEFAULT_IMG_PATH:
        return True
    # Zapisz kopię oryginału jako JPEG
    base_image = Image.open(instance.image.path)
    filename = os.path.splitext(instance.image.path)[0]
    base_image.save("{}.jpg".format(filename), 'JPEG')
    # Rozmiar obrazów i miniatur pobieramy z ustawień globalnych
    width, height = settings.DEFAULT_IMG_SIZE
    t_width, t_height = settings.DEFAULT_THUMB_SIZE
    # Normalne obrazki w pełnych wymiarach
    image = resize_image(base_image, (width * 2, height * 2))
    image.save("{}_fx@2x.jpg".format(filename), 'JPEG')
    image = resize_image(base_image, (width, height))
    image.save("{}_fx.jpg".format(filename), 'JPEG')
    # Miniatury do pokazania w widokach list i aktywności
    image = resize_image(base_image, (t_width * 2, t_height * 2))
    image.save("{}_thumbnail@2x.jpg".format(filename), 'JPEG')
    image = resize_image(base_image, (t_width, t_height))
    image.save("{}_thumbnail.jpg".format(filename), 'JPEG')


Returns path to fixed images ( i . e . images with proper suffix ) based on full path to image provided as argument .

def fix_path(filepath, size='BIG'):
    """
    Returns path to fixed images (i.e. images with proper suffix) based on
    full path to image provided as argument.
    """
    path_parts = filepath.split('/')
    name = path_parts.pop()
    size_prefix = "%dx%d_" % settings.CO_THUMB_SIZES.get(size.upper())
    path_parts.append(size_prefix + name)
    return "/".join(path_parts)

def fix_path ( filepath , size = 'BIG' ) : path_parts = filepath . split ( '/' ) name = path_parts . pop ( ) size_prefix = "%dx%d_" % settings . CO_THUMB_SIZES . get ( size . upper ( ) ) path_parts . append ( size_prefix + name ) return "/" . join ( path_parts )


Takes PIL image and tuple with width and height and performs smart cut .

def crop(image, max_size):
    """ Takes PIL image and tuple with width and height and performs "smart cut".
    """
    max_w, max_h = max_size
    width, height = image.getdata().size

    # Find ratio
    if height > width:
        ratio = float(max_w)/float(width)
        image = image.resize((max_w, int(height*ratio)), Image.ANTIALIAS)
        box = (0, 0, max_w, max_h)
    else:
        ratio = float(max_h)/float(height)
        new_width = int(width*ratio)
        image = image.resize((new_width, max_h), Image.ANTIALIAS)
        start_x = 0
        x_factor = max_w
        if new_width > max_w:
            start_x = int((float(new_width)-float(max_w))/2)
        if new_width < max_w:
            nratio = float(max_w)/float(new_width)
            cw, ch = image.getdata().size
            image = image.resize((max_w, int(float(ch)*nratio)), Image.ANTIALIAS)
        stop_x = start_x + x_factor
        box = (start_x, 0, stop_x, max_h)

    return image.crop(box)

def
crop
(
image
,
max_size
)
:
max_w
,
max_h
=
max_size
width
,
height
=
image
.
getdata
(
)
.
size
# Find ratio
if
height
>
width
:
ratio
=
float
(
max_w
)
/
float
(
width
)
image
=
image
.
resize
(
(
max_w
,
int
(
height
*
ratio
)
)
,
Image
.
ANTIALIAS
)
box
=
(
0
,
0
,
max_w
,
max_h
)
else
:
ratio
=
float
(
max_h
)
/
float
(
height
)
new_width
=
int
(
width
*
ratio
)
image
=
image
.
resize
(
(
new_width
,
max_h
)
,
Image
.
ANTIALIAS
)
start_x
=
0
x_factor
=
max_w
if
new_width
>
max_w
:
start_x
=
int
(
(
float
(
new_width
)
float
(
max_w
)
)
/
2
)
if
new_width
<
max_w
:
nratio
=
float
(
max_w
)
/
float
(
new_width
)
cw
,
ch
=
image
.
getdata
(
)
.
size
image
=
image
.
resize
(
(
max_w
,
int
(
float
(
ch
)
*
nratio
)
)
,
Image
.
ANTIALIAS
)
stop_x
=
start_x
+
x_factor
box
=
(
start_x
,
0
,
stop_x
,
max_h
)
return
image
.
crop
(
box
)


Creates thumbs for all selected sizes for ContentObjectPicture .

def generate_thumbs(filepath):
    """ Creates thumbs for all selected sizes for ContentObjectPicture.
    """
    image = Image.open(filepath)

    # First convert all uploaded originals to JPG format
    image = image.convert('RGB')
    image.save(filepath, 'JPEG')

    for label, size in settings.CO_THUMB_SIZES.iteritems():
        thumb = crop(image.copy(), size)
        thumb.save(fix_path(filepath, label), 'JPEG')


Scales the image to the given width preserving proportions .

def resize_image(image, max_width):
    """ Scales the image to the given width, preserving proportions. """
    img_width, img_height = image.getdata().size
    if img_width >= max_width and img_width >= img_height:
        # Obrazek do przeskalowania przez `thumbnail`
        img_copy = image.copy()
        img_copy.thumbnail((max_width, max_width), Image.ANTIALIAS)
        return img_copy
    ratio = float(max_width) / float(img_width)
    return image.resize((max_width, int(float(img_height) * ratio)), Image.ANTIALIAS)


Crops the image to the exact sizes preserves as much as it can .

def perform_smart_cut(image, size):
    """ Crops the image to the exact sizes, preserves as much as it can. """
    if size[0] >= size[1]:
        image = resize_image(image, size[0])
        new_width, new_height = image.getdata().size
        start_x = 0
        start_y = (new_height - size[1]) / 2
        stop_x = start_x + size[0]
        stop_y = start_y + size[1]

    box = (start_x, start_y, stop_x, stop_y)
    return image.crop(box)

def perform_smart_cut ( image , size ) : if size [ 0 ] >= size [ 1 ] : image = resize_image ( image , size [ 0 ] ) new_width , new_height = image . getdata ( ) . size start_x = 0 start_y = ( new_height - size [ 1 ] ) / 2 stop_x = start_x + size [ 0 ] stop_y = start_y + size [ 1 ] box = ( start_x , start_y , stop_x , stop_y ) return image . crop ( box )


def crop_thumbnail(image, size):
    """ Cuts out a minature from the cropped background image """
    max_w, max_h = size
    width, height = image.getdata().size
    new_width = int(width * float(max_h)/float(height))
    startx = int((new_width - max_w) / 2)
    image = image.resize((new_width, max_h), Image.ANTIALIAS)
    box = (startx, 0, startx + max_w, max_h)
    return image.crop(box)

def crop_thumbnail ( image , size ) : max_w , max_h = size width , height = image . getdata ( ) . size new_width = int ( width * float ( max_h ) / float ( height ) ) startx = int ( ( new_width - max_w ) / 2 ) image = image . resize ( ( new_width , max_h ) , Image . ANTIALIAS ) box = ( startx , 0 , startx + max_w , max_h ) return image . crop ( box )


Creates image minatures and cropped background images for original files on the server .

def fix_images():
    """ Creates image minatures and cropped background images for original files on the server."""
    import re
    from django.conf import settings

    max_width, max_height = settings.BACKGROUND_IMAGE_SIZE
    dirname = os.path.join(settings.BASE_DIR, 'media/img/locations')
    for filename in os.listdir(dirname):
        if not re.match(r'\w+_\d+', filename):
            im = ImageManager(os.path.join(dirname, filename), dirname)
            im.fixed_thumb(max_width, max_height)

def fix_images ( ) : import re from django . conf import settings max_width , max_height = settings . BACKGROUND_IMAGE_SIZE dirname = os . path . join ( settings . BASE_DIR , 'media/img/locations' ) for filename in os . listdir ( dirname ) : if not re . match ( r'\w+_\d+' , filename ) : im = ImageManager ( os . path . join ( dirname , filename ) , dirname ) im . fixed_thumb ( max_width , max_height )


def _open_image(cls, filename):
        """ Returns PIL image if it is possible. """
        try:
            return Image.open(filename)
        except (IOError, OSError):
            raise Exception(u"Cannot open image file '%s'" % filename)

def
_open_image
(
cls
,
filename
)
:
try
:
return
Image
.
open
(
filename
)
except
(
IOError
,
OSError
)
:
raise
Exception
(
u"Cannot open image file '%s'"
%
filename
)


def create_filename(self, suffix, format='jpg'):
        """ A Helper that will create a proper name for the file"""
        file, ext = os.path.splitext(self.filename)
        return os.path.join(self.dir, "{}_{}.{}".format(file, suffix, format))

def create_filename ( self , suffix , format = 'jpg' ) : file , ext = os . path . splitext ( self . filename ) return os . path . join ( self . dir , "{}_{}.{}" . format ( file , suffix , format ) )


def resize(self, width, height):
        """ We scale the image and preserve the proportions"""
        image_w, image_h = self.image.size
        aspect_ratio = image_w / float(image_h)

        if image_h > image_w:
            ratio = width / float(image_w)
            return self.image.resize((width, int(image_h * ratio)), Image.ANTIALIAS)
        else:
            ratio = height / float(image_h)
            return self.image.resize((int(image_w * ratio), height), Image.ANTIALIAS)

def resize ( self , width , height ) : image_w , image_h = self . image . size aspect_ratio = image_w / float ( image_h ) if image_h > image_w : ratio = width / float ( image_w ) return self . image . resize ( ( width , int ( image_h * ratio ) ) , Image . ANTIALIAS ) else : ratio = height / float ( image_h ) return self . image . resize ( ( int ( image_w * ratio ) , height ) , Image . ANTIALIAS )


We crop and scale the image and preserve the proportions . Useful for minatures with equal proportions . The method makes sure that as much as possible of the original image will be visible .

def smart_cut(self, width, height):
        """
        We crop and scale the image and preserve the proportions. Useful for
        minatures with equal proportions. The method makes sure that as much
        as possible of the original image will be visible.
        """
        return perform_smart_cut(self.image, (width, height))

def smart_cut ( self , width , height ) : return perform_smart_cut ( self . image , ( width , height ) )


Creates a minature optimized for a given size .

def fixed_thumb(self, width, height):
        """ Creates a minature optimized for a given size. """
        img = self.smart_cut(width * 2, height * 2)
        img.save(self.create_filename("{}x{}@2x".format(width, height)), 'JPEG')
        img = img.resize((width, height), Image.ANTIALIAS)
        img.save(self.create_filename("{}x{}".format(width, height)), 'JPEG')

        # TODO: rozmiary miniatur powinny być zdefiniowane w ustawieniach
        img = crop_thumbnail(img, (270, 190))
        img.save(self.create_filename("{}x{}".format(270, 190)), 'JPEG')


FIXME : tu nie wszystko będzie teraz potrzebne .

def __init__(self, filename, dirname=None):
        """ FIXME: tu nie wszystko będzie teraz potrzebne. """
        self.filename = filename.split('/')[-1]
        self.image = self._open_image(filename)
        self.dir = dirname if dirname is not None else os.getcwd()

def __init__ ( self , filename , dirname = None ) : self . filename = filename . split ( '/' ) [ - 1 ] self . image = self . _open_image ( filename ) self . dir = dirname if dirname is not None else os . getcwd ( )


Check if gallery directory exists or create new one if not .

def check(gallery):
    """ Check if gallery directory exists or create new one if not.
    """
    if not gallery.dirname:
        gallery.dirname = uuid4().hex
    full_path = os.path.join(CONTENT_IMAGE_DIRNAME, gallery.dirname)
    if not os.path.exists(full_path):
        os.makedirs(full_path)

def check ( gallery ) : if not gallery . dirname : gallery . dirname = uuid4 ( ) . hex full_path = os . path . join ( CONTENT_IMAGE_DIRNAME , gallery . dirname ) if not os . path . exists ( full_path ) : os . makedirs ( full_path )


def rmdir(gallery):
    """ Delete gallery image directory.
    """
    full_path = os.path.join(CONTENT_IMAGE_DIRNAME, gallery.dirname)
    if os.path.exists(full_path):
        shutil.rmtree(full_path)

def rmdir ( gallery ) : full_path = os . path . join ( CONTENT_IMAGE_DIRNAME , gallery . dirname ) if os . path . exists ( full_path ) : shutil . rmtree ( full_path )


def upload_path(instance, filename):
    """ Provides unique filename.
    """
    return 'galleries/{}/{}.jpg'.format(instance.gallery.dirname, uuid4().hex)

def upload_path ( instance , filename ) : return 'galleries/{}/{}.jpg' . format ( instance . gallery . dirname , uuid4 ( ) . hex )


Delete original and all fixed files for picture .

def massrm(picture):
    """ Delete original and all fixed files for picture.
    """
    clean_filename, ext = os.path.splitext(picture.image.path.split('/')[-1])
    full_path = os.path.join(CONTENT_IMAGE_DIRNAME, picture.gallery.dirname)
    for root, dirnames, files in os.walk(full_path):
        for name in files:
            if clean_filename in name:
                os.unlink(os.path.join(root, name))

def massrm ( picture ) : clean_filename , ext = os . path . splitext ( picture . image . path . split ( '/' ) [ - 1 ] ) full_path = os . path . join ( CONTENT_IMAGE_DIRNAME , picture . gallery . dirname ) for root , dirnames , files in os . walk ( full_path ) : for name in files : if clean_filename in name : os . unlink ( os . path . join ( root , name ) )


Returns picture url . This function is most useful for views .

def url(self):
        """
        Returns picture url. This function is most useful for views.
        """
        return settings.MEDIA_URL + self.user.username + '/' + self.picture_name

def url ( self ) : return settings . MEDIA_URL + self . user . username + '/' + self . picture_name


This function returns url to thumbnail of photo . Size parameter is man - datory and related to thumb sizes declared in views module . It should be touple or list containing images width and height .

def get_thumbnail(self, size):
        """
        This function returns url to thumbnail of photo. Size parameter is man-
        datory and related to thumb sizes declared in views module. It should
        be touple or list containing images width and height.
        """
        thumbname = str(size[0]) + 'x' + str(size[1]) + '_' + self.picture_name
        return settings.MEDIA_URL + self.user.username + '/thumbs/' + thumbname

def get_thumbnail ( self , size ) : thumbname = str ( size [ 0 ] ) + 'x' + str ( size [ 1 ] ) + '_' + self . picture_name return settings . MEDIA_URL + self . user . username + '/thumbs/' + thumbname


def url(self):
        """ Returns picture url. This function is most useful for views.
        """
        return settings.MEDIA_URL + self.location.slug + '/' + self.picture_name

def url ( self ) : return settings . MEDIA_URL + self . location . slug + '/' + self . picture_name


def get_thumbnail(self, size):
        """
        This function returns url to thumbnail of photo. Size parameter is man-
        datory and related to thumb sizes declared in views module. It should
        be touple or list containing images width and height.
        """
        thumbname = str(size[0]) + 'x' + str(size[1]) + '_' + self.picture_name
        return settings.MEDIA_URL + self.location.slug + '/thumbs/' + thumbname

def get_thumbnail ( self , size ) : thumbname = str ( size [ 0 ] ) + 'x' + str ( size [ 1 ] ) + '_' + self . picture_name return settings . MEDIA_URL + self . location . slug + '/thumbs/' + thumbname


Notify users that someone voted for their ideas .

def vote_notification(sender, instance, created, **kwargs):
    """ Notify users that someone voted for their ideas. """
    if instance.user == instance.idea.creator or not created:
        return True
    suff = "up" if instance.status == 1 else "down"
    notify(instance.user, instance.idea.creator,
           key="vote",
           verb="voted for your idea",
           action_object=instance,
           action_target=instance.idea)

def
vote_notification
(
sender
,
instance
,
created
,
*
*
kwargs
)
:
if
instance
.
user
==
instance
.
idea
.
creator
or
not
created
:
return
True
suff
=
"up"
if
instance
.
status
==
1
else
"down"
notify
(
instance
.
user
,
instance
.
idea
.
creator
,
key
=
"vote"
,
verb
=
"voted for your idea"
,
action_object
=
instance
,
action_target
=
instance
.
idea
)


Create voting buttons and statistics . We provide common class names and Data parameters so that scripts can be easily added . Here we determine the initial state of buttons .

def vote_area(context, obj):
    """ Create voting buttons and statistics. We provide common class names and
        Data parameters so that scripts can be easily added. Here, we determine
        the initial state of buttons.
    """
    if context.get('experiment') is not None:
        template = loader.get_template('ideas/vote_area_b.html')
    else:
        template = loader.get_template('ideas/vote_area.html')
    if obj is None:
        return ''
    user = context['user']
    ctx = Context({'user': user, 'idea': obj, 'request': context['request']})
    if user.is_anonymous():
        pass
    elif len(obj.vote_set.filter(user=user, status=1)):
        ctx.update({'voted_up': True, })
    elif len(obj.vote_set.filter(user=user, status=2)):
        ctx.update({'voted_no': True, })
    return template.render(ctx)

def vote_area ( context , obj ) : if context . get ( 'experiment' ) is not None : template = loader . get_template ( 'ideas/vote_area_b.html' ) else : template = loader . get_template ( 'ideas/vote_area.html' ) if obj is None : return '' user = context [ 'user' ] ctx = Context ( { 'user' : user , 'idea' : obj , 'request' : context [ 'request' ] } ) if user . is_anonymous ( ) : pass elif len ( obj . vote_set . filter ( user = user , status = 1 ) ) : ctx . update ( { 'voted_up' : True , } ) elif len ( obj . vote_set . filter ( user = user , status = 2 ) ) : ctx . update ( { 'voted_no' : True , } ) return template . render ( ctx )


Notify followers about new blog entries related to some other objects .

def blog_entry_created_action(sender, instance, created, **kwargs):
    """
    Notify followers about new blog entries related to some other objects.
    """
    if not created:
        return True
    if instance.content_object is None:
        action.send(instance.author,
                    action_object=instance,
                    verb=_('created'))
    else:
        action.send(instance.author,
                    action_object=instance,
                    verb=_('created'),
                    target=instance.content_object)

def blog_entry_created_action ( sender , instance , created , * * kwargs ) : if not created : return True if instance . content_object is None : action . send ( instance . author , action_object = instance , verb = _ ( 'created' ) ) else : action . send ( instance . author , action_object = instance , verb = _ ( 'created' ) , target = instance . content_object )


Return list of blog entries published ( tied to ) given object .

def get_published_in(self, obj):
        """
        Return list of blog entries published (tied to) given object.
        """
        ct = ContentType.objects.get_for_model(obj).pk
        return super(BlogManager, self).get_queryset()\
            .filter(content_type__id=ct, object_id=obj.pk)

def get_published_in ( self , obj ) : ct = ContentType . objects . get_for_model ( obj ) . pk return super ( BlogManager , self ) . get_queryset ( ) . filter ( content_type__id = ct , object_id = obj . pk )


Return all blog entries created by given user .

def get_published_by(self, user):
        """
        Return all blog entries created by given user.
        """
        return super(BlogManager, self).get_queryset().filter(author=user)

def get_published_by ( self , user ) : return super ( BlogManager , self ) . get_queryset ( ) . filter ( author = user )


Count simpleblog entries published for selected content object .

def newscounter(obj):
    """ Count simpleblog entries published for selected content object.
	"""
    return BlogEntry.objects.get_published_in(obj).count()

def newscounter ( obj ) : return BlogEntry . objects . get_published_in ( obj ) . count ( )


Make sure that only owner can mark notification as read .

def get_object(self):
        """ Make sure that only owner can mark notification as read. """
        self.object = super(NotificationView, self).get_object()
        if self.object.user != self.request.user:
            raise PermissionDenied
        self.object.read()
        return self.object

def get_object ( self ) : self . object = super ( NotificationView , self ) . get_object ( ) if self . object . user != self . request . user : raise PermissionDenied self . object . read ( ) return self . object


Serialize object instcane via native Django seraializer and return as JSON .

def serializer_object(obj):
    """
    Serialize object instcane via native Django seraializer and return as JSON.
    """
    if obj is None:
        return None
    data = json.loads(dj_serializers.serialize('json', [obj,]))[0]
    if hasattr(obj, 'get_absolute_url'):
        data['url'] = obj.get_absolute_url()
    return data

def serializer_object ( obj ) : if obj is None : return None data = json . loads ( dj_serializers . serialize ( 'json' , [ obj , ] ) ) [ 0 ] if hasattr ( obj , 'get_absolute_url' ) : data [ 'url' ] = obj . get_absolute_url ( ) return data


Try to find most appropriate url for this kind of notification .

def get_action_url(self, obj):
        """ Try to find most appropriate url for this kind of notification. """
        # If there is no better match, point to actor profile url
        action_url = obj.action_actor.profile.get_absolute_url()
        # Fallback if action_target is undefined:
        if obj.action_object is not None:
            if hasattr(obj.action_object, 'get_absolute_url'):
                action_url = obj.action_object.get_absolute_url()
        # And most preferred option - get url from action target
        elif obj.action_target is not None:
            if hasattr(obj.action_target, 'get_absolute_url'):
                action_url = obj.action_target.get_absolute_url()
        return action_url


def retrieve(self, request, pk=None):
        """
        Be sure to mark this object as read.
        """
        obj = self.get_object()
        obj.read()
        return super(NotificationViewSet, self).retrieve(request, pk)

def retrieve ( self , request , pk = None ) : obj = self . get_object ( ) obj . read ( ) return super ( NotificationViewSet , self ) . retrieve ( request , pk )


Create proper notification based on passed values .

def notify(actor, user, **kwargs):
    """ Create proper notification based on passed values. """
    notify = Notification(user=user, action_actor=actor)
    action_object = kwargs.get('action_object')
    if action_object is not None:
        notify.action_object_ct = ContentType.objects.get_for_model(action_object)
        notify.action_object_id = action_object.pk
    action_target = kwargs.get('action_target')
    if action_target is not None:
        notify.action_target_ct = ContentType.objects.get_for_model(action_target)
        notify.action_target_id = action_target.pk
    keyword = kwargs.get('key')
    if keyword is not None:
        notify.key = keyword
    verb = kwargs.get('verb')
    if verb is not None:
        notify.action_verb = verb
    notify.save()

def notify ( actor , user , * * kwargs ) : notify = Notification ( user = user , action_actor = actor ) action_object = kwargs . get ( 'action_object' ) if action_object is not None : notify . action_object_ct = ContentType . objects . get_for_model ( action_object ) notify . action_object_id = action_object . pk action_target = kwargs . get ( 'action_target' ) if action_target is not None : notify . action_target_ct = ContentType . objects . get_for_model ( action_target ) notify . action_target_id = action_target . pk keyword = kwargs . get ( 'key' ) if keyword is not None : notify . key = keyword verb = kwargs . get ( 'verb' ) if verb is not None : notify . action_verb = verb notify . save ( )


This method takes user instance and returns number of unread notifications belonging to him .

def count_unread_for_user(self, user):
        """ This method takes user instance and returns number of unread
        notifications belonging to him. """
        qs = super(NotificationManager, self).get_queryset()
        return qs.filter(user=user, checked_at__isnull=True).count()

def count_unread_for_user ( self , user ) : qs = super ( NotificationManager , self ) . get_queryset ( ) return qs . filter ( user = user , checked_at__isnull = True ) . count ( )


Find all unread notifications for particular user instance .

def unread_for_user(self, user):
        """ Find all unread notifications for particular user instance. """
        qs = super(NotificationManager, self).get_queryset()
        return qs.filter(user=user, checked_at__isnull=True)

def unread_for_user ( self , user ) : qs = super ( NotificationManager , self ) . get_queryset ( ) return qs . filter ( user = user , checked_at__isnull = True )


Give the number of unread notifications for a user or nothing ( an empty string ) for an anonymous user . Storing the count in a variable for further processing is advised such as :: { % unread_notifications as unread_count % } ... { % if unread_count % } You have <strong > {{ unread_count }} < / strong > unread notifications . { % endif % }

def unread_notifications(parser, token):
    """
    Give the number of unread notifications for a user,
    or nothing (an empty string) for an anonymous user.
    Storing the count in a variable for further processing is advised, such as::
        {% unread_notifications as unread_count %}
        ...
        {% if unread_count %}
            You have <strong>{{ unread_count }}</strong> unread notifications.
        {% endif %}
    """
    bits = token.split_contents()
    if len(bits) > 1:
        if len(bits) != 3:
            raise TemplateSyntaxError("'{0}' tag takes no argument or exactly two arguments".format(bits[0]))
        if bits[1] != 'as':
            raise TemplateSyntaxError("First argument to '{0}' tag must be 'as'".format(bits[0]))
        return UnreadCountNode(bits[2])
    else:
        return UnreadCountNode()


Return the count of unread notifications for the user found in context ( may be 0 ) or an empty string .

def render(self, context):
        """
        Return the count of unread notifications for the user found in context,
        (may be 0) or an empty string.
        """
        try:
            user = context['user']
            if user.is_anonymous():
                count = ''
            else:
                count = Notification.objects.count_unread_for_user(user)
        except (KeyError, AttributeError):
            count = ''
        if self.asvar:
            context[self.asvar] = count
            return ''
        return count

def render ( self , context ) : try : user = context [ 'user' ] if user . is_anonymous ( ) : count = '' else : count = Notification . objects . count_unread_for_user ( user ) except ( KeyError , AttributeError ) : count = '' if self . asvar : context [ self . asvar ] = count return '' return count


This view should be used along with some front - end scripts . This way we can exclude robots from records .

def visit_view(request, ct, pk):
    """
    This view should be used along with some front-end scripts.
    This way we can exclude robots from records.
    """
    visit = Visit.objects.create(ip=get_ip(request), content_type_id=ct, object_id=pk)
    return HttpResponse(json.dumps({'id': visit.pk, }), content_type="application/json")

def visit_view ( request , ct , pk ) : visit = Visit . objects . create ( ip = get_ip ( request ) , content_type_id = ct , object_id = pk ) return HttpResponse ( json . dumps ( { 'id' : visit . pk , } ) , content_type = "application/json" )


def count_for_object(self, instance):
        """ Returns total count for this object. """
        qs = super(VisitManager, self).get_queryset()
        ct = ContentType.objects.get_for_model(instance)
        return sum([x.visit_count for x in qs.filter(
            content_type=ct, object_id=instance.pk)])

def count_for_object ( self , instance ) : qs = super ( VisitManager , self ) . get_queryset ( ) ct = ContentType . objects . get_for_model ( instance ) return sum ( [ x . visit_count for x in qs . filter ( content_type = ct , object_id = instance . pk ) ] )


Count only one visit for each IP address .

def count_unique_for_object(self, instance):
        """ Count only one visit for each IP address. """
        qs = super(VisitManager, self).get_queryset()
        ct = ContentType.objects.get_for_model(instance)
        return len(qs.filter(content_type=ct, object_id=instance.pk))

def count_unique_for_object ( self , instance ) : qs = super ( VisitManager , self ) . get_queryset ( ) ct = ContentType . objects . get_for_model ( instance ) return len ( qs . filter ( content_type = ct , object_id = instance . pk ) )


AJAX request required decorator use it in your views :

def ajax_required(f):
    """
    AJAX request required decorator
    use it in your views:

    @ajax_required
    def my_view(request):
        ....

    """
    def wrap(request, *args, **kwargs):
            if not request.is_ajax():
                return HttpResponseBadRequest()
            return f(request, *args, **kwargs)
    wrap.__doc__=f.__doc__
    wrap.__name__=f.__name__
    return wrap

def ajax_required ( f ) : def wrap ( request , * args , * * kwargs ) : if not request . is_ajax ( ) : return HttpResponseBadRequest ( ) return f ( request , * args , * * kwargs ) wrap . __doc__ = f . __doc__ wrap . __name__ = f . __name__ return wrap


Helper function - adds data - ct and data - pk to HTML attributes .

def render_node(counter, instance):
    """
    Helper function - adds data-ct and data-pk to HTML attributes.
    """
    ct = ContentType.objects.get_for_model(instance).pk
    return '{}'\
        .format(ct, instance.pk, counter)


Returns total visit count for specified object .

def visit_counter(obj):
    """
    Returns total visit count for specified object.
    """
    return render_node(Visit.objects.count_for_object(obj), obj)

def visit_counter ( obj ) : return render_node ( Visit . objects . count_for_object ( obj ) , obj )


Returns visit count unique for ip addresses .

def unique_counter(obj):
    """
    Returns visit count unique for ip addresses.
    """
    return render_node(Visit.objects.count_unique_for_object(obj), obj)

def unique_counter ( obj ) : return render_node ( Visit . objects . count_unique_for_object ( obj ) , obj )


Updates all cached map clusters related to locations .

def update_marker_cluster_cache():
    """ Updates all cached map clusters related to locations. """
    create_country_clusters()
    for location in Location.objects.filter(kind__in=['PPLA', 'PPLC',]):
        make_region_cluster(location)

def update_marker_cluster_cache ( ) : create_country_clusters ( ) for location in Location . objects . filter ( kind__in = [ 'PPLA' , 'PPLC' , ] ) : make_region_cluster ( location )


There is a chance that deleted objects will stay on map .

def clear_empty_markers():
    """ There is a chance that deleted objects will stay on map. """
    for marker in MapPointer.objects.all():
        if marker.content_object is None:
            marker.delete()

def clear_empty_markers ( ) : for marker in MapPointer . objects . all ( ) : if marker . content_object is None : marker . delete ( )


Create marker for new created object . Mark it s location approprietly if it is location or object related to location . It needs models with latitude and longitude fields to work so it s mostly useful for locations .

def create_marker(sender, instance, created, **kwargs):
    """ Create marker for new created object. Mark it's location approprietly
        if it is location or object related to location. It needs models with
        latitude and longitude fields to work, so it's mostly useful for
        locations.
    """
    if not hasattr(instance, 'latitude') or not hasattr(instance, 'longitude'):
        return False

    lat = instance.latitude
    lng = instance.longitude

    if not lat or not lng:
        return

    # Try to remove obsolete markers if lat or lng has changed
    for m in MapPointer.objects.for_model(instance):
        m.delete()

    try:
        mp = MapPointer.objects.create_for_object(instance, lat, lng)
    except IntegrityError:
        mp = MapPointer.objects.for_model(instance).first()

    return mp


QuerySet for all pointers for a particular model .

def for_model(self, model):
        """ QuerySet for all pointers for a particular model.
        """
        ct = ContentType.objects.get_for_model(model)
        qs = self.get_queryset().filter(content_type=ct)
        if isinstance(model, models.Model):
            qs = qs.filter(object_pk=force_text(model._get_pk_val()))
        return qs

def for_model ( self , model ) : ct = ContentType . objects . get_for_model ( model ) qs = self . get_queryset ( ) . filter ( content_type = ct ) if isinstance ( model , models . Model ) : qs = qs . filter ( object_pk = force_text ( model . _get_pk_val ( ) ) ) return qs


QuerySet for all pointers for particular location .

def for_location(self, location):
        """ QuerySet for all pointers for particular location.
        """
        return self.get_queryset().filter(location=location)

def for_location ( self , location ) : return self . get_queryset ( ) . filter ( location = location )


Creates new map pointer for given object on passed latitude and longitude .

def create_for_object(self, obj, lat, lng, **kwargs):
        """ Creates new map pointer for given object on passed latitude and longitude.
        """
        pointer = self.model(latitude=lat, longitude=lng, object_pk=obj.pk,
                             content_type=ContentType.objects.get_for_model(obj))
        if obj._meta.model_name == 'location':
            pointer.location = obj
        elif hasattr(obj, 'location'):
            pointer.location = obj.location
        pointer.save()
        return pointer

def create_for_object ( self , obj , lat , lng , * * kwargs ) : pointer = self . model ( latitude = lat , longitude = lng , object_pk = obj . pk , content_type = ContentType . objects . get_for_model ( obj ) ) if obj . _meta . model_name == 'location' : pointer . location = obj elif hasattr ( obj , 'location' ) : pointer . location = obj . location pointer . save ( ) return pointer


Simple marker list filter . It takes latitude and longitude as arguments and fetch pointers in distance of factor degrees from this point . Filters is array of content type id s to fetch . If None is set nothing will be returned . If you pass location pk only markers related to this location will be fetched .

def filter_markers(lat, lng, factor=1.0, filters=None, location_pk=None):
    """
    Simple marker list filter. It takes latitude and longitude as arguments and
    fetch pointers in distance of `factor` degrees from this point.

    Filters is array of content type id's to fetch. If None is set, nothing will be returned.

    If you pass location pk only markers related to this location will be fetched.
    """
    if filters is None:
        return []

    # if location_pk is not None:
    #     qs = MapPointer.objects.for_location(
    #         get_object_or_404(Location, pk=location_pk))
    # else:
    #     qs = MapPointer.objects.all()
    qs = MapPointer.objects.all()

    return qs.filter(
        latitude__gt=float(lat) - float(factor),
        latitude__lt=float(lat) + float(factor),
        longitude__gt=float(lng) - float(factor),
        longitude__lt=float(lng) + float(factor),
        content_type__in=[int(x) for x in filters.split(',') if x]
    )

#     qs = MapPointer.objects.for_location(


This function takes region main location as argument and creates cache .

def make_region_cluster(city):
    """ This function takes region main location as argument and creates cache. """
    count = MapPointer.objects.filter(
        location__in=city.parent.get_children_id_list()).count()
    redis_cache.set(str(city.pk) + '_childlist', count, timeout=None)
    logger.info("Created cluster for region {} with {} items".format(city.pk, count))
    return count


Create clusters for regions - usable in medium zoom . Function takes latitude and longitude of current map center as strings or numbers .

def create_region_clusters(lat, lng, zoom):
    """
    Create clusters for regions - usable in medium zoom. Function takes latitude
    and longitude of current map center as strings or numbers.
    """
    clusters = []

    if int(zoom) == 6:
        factor = 40.0
    elif int(zoom) > 6 and int(zoom) < 9:
        factor = 20.0
    else:
        factor = 10.0

    max_lat = float(lat) + factor
    max_lng = float(lng) + factor
    min_lat = float(lat) - factor
    min_lng = float(lng) - factor

    main_locations = Location.objects.filter(
        kind__in=['PPLA','PPLC'],
        latitude__gt=min_lat,
        latitude__lt=max_lat,
        longitude__gt=min_lng,
        longitude__lt=max_lng)

    for l in main_locations:
        # we can use this value directly - update signal takes care of cache.
        count = redis_cache.get(str(l.pk) + '_childlist')
        if count is None:
            count = make_region_cluster(l)
        cluster = {
            'lat': l.latitude,
            'lng': l.longitude,
            'counter': count,
        }
        clusters.append(cluster)
    return clusters