Initial Import.

This commit is contained in:
2013-03-31 23:15:07 +01:00
commit c19f2f5562
66 changed files with 1780 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
from .stores import StoreListView, StoreDetailView, StoreUpdateView, StoreCreateView
from .chains import ChainListView, ChainDetailView
from .search import DistanceSearchView
from .claims import ClaimCreateView
from .misc import MapView

View File

@@ -0,0 +1,20 @@
from django.views.generic import ListView, DetailView
from .mixins import EditorCheckMixin
from ..models import Chain
class ChainListView(ListView):
model = Chain
paginate_by = 10
def get_queryset(self):
qs = super(ChainListView, self).get_queryset()
return qs.filter(active=True).prefetch_related('stores')
class ChainDetailView(EditorCheckMixin, DetailView):
model = Chain
def get_queryset(self):
qs = super(ChainDetailView, self).get_queryset()
return qs.filter(active=True).prefetch_related('stores', 'stores__address')

View File

@@ -0,0 +1,44 @@
from django.views.generic.edit import CreateView
from django.core.urlresolvers import reverse
from django.contrib.contenttypes.models import ContentType
from django.contrib import messages
from ..forms import ClaimRequestForm
from ..models import ClaimRequest
class ClaimCreateView(CreateView):
model = ClaimRequest
target_model = None
form_class = ClaimRequestForm
template_name = 'stores/claim_form.html'
def get(self, request, *args, **kwargs):
self.target_obj = self.get_target_object()
return super(ClaimCreateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.target_obj = self.get_target_object()
return super(ClaimCreateView, self).post(request, *args, **kwargs)
def get_target_object(self):
obj_slug = self.kwargs.get('slug')
return self.target_model.objects.get(slug=obj_slug)
def get_context_data(self, **kwargs):
ctx = super(ClaimCreateView, self).get_context_data(**kwargs)
ctx.update({
'target_obj': self.target_obj,
})
return ctx
def form_valid(self, form):
obj = form.save(commit=False)
obj.object_id = self.target_obj.pk
obj.object_type = ContentType.objects.get_for_model(self.target_model)
obj.user = self.request.user
obj.save()
messages.success(self.request, 'Your claim request for %s has been successfully submitted for review.' % self.target_obj)
return super(ClaimCreateView, self).form_valid(form)
def get_success_url(self):
return reverse('store-detail', args=[self.target_obj.slug])

32
app/stores/views/misc.py Normal file
View File

@@ -0,0 +1,32 @@
from django.core.cache import cache
from django.views.generic import ListView
from ..models import Chain, Store
class MapView(ListView):
model = Store
template_name_suffix = '_map'
def get_context_data(self, **kwargs):
ctx = super(MapView, self).get_context_data(**kwargs)
stores = cache.get('store_count')
chains = cache.get('chain_count')
if not stores:
stores = Store.objects.filter(active=True).count()
cache.set('store_count', stores, 600)
if not chains:
chains = Chain.objects.filter(active=True).count()
cache.set('chain_count', chains, 600)
ctx.update({
'store_count': stores,
'chain_count': chains,
})
return ctx
def get_queryset(self):
qs = super(MapView, self).get_queryset()
return qs.filter(active=True).select_related('address')

View File

@@ -0,0 +1,55 @@
from django.http import Http404
from haystack.query import SearchQuerySet
from haystack.inputs import AutoQuery
class EditorCheckMixin(object):
"""
A mixin to check if the object is inactive to only show it to editors or superusers
"""
def is_editor(self, object):
if self.request.user.is_superuser or self.request.user == object.editor:
return True
return False
def get_object(self, queryset=None):
obj = super(EditorCheckMixin, self).get_object(queryset)
if not obj.active:
if not self.is_editor(obj):
raise Http404
return obj
def get_context_data(self, **kwargs):
ctx = super(EditorCheckMixin, self).get_context_data(**kwargs)
ctx.update({
'is_editor': self.is_editor(self.object)
})
return ctx
class HaystackSearchListMixin(object):
"""
Adds searching via Haystack to a regular ListView
"""
search_parameter = 'q'
def get_search_terms(self):
return self.request.GET.get(self.search_parameter, None)
def get_search_filter(self):
return {
'content': AutoQuery(self.get_search_terms())
}
def haystack_search(self):
return SearchQuerySet().filter(**self.get_search_filter()).models(self.model)
def get_queryset(self):
if self.get_search_terms():
res = self.haystack_search()
if res.count() == 0:
return self.model.objects.none()
return self.model.objects.filter(pk__in=[r.object.pk for r in res.load_all()])
else:
return super(HaystackSearchListMixin, self).get_queryset()

View File

@@ -0,0 +1,42 @@
from django.views.generic import ListView
from haystack.query import SearchQuerySet
from haystack.utils.geo import Point, D
from ..models import Store
from ..utils import caching_geo_lookup
class DistanceSearchView(ListView):
template_name = 'stores/store_search.html'
distance = 25
def get_location(self):
# TODO: geopy the location based on kwargs
location = self.request.GET.get('location')
lat = self.request.GET.get('lat')
lng = self.request.GET.get('lng')
if location:
name, geo = caching_geo_lookup(location)
elif lat and lng:
name, geo = caching_geo_lookup('%s,%s' % (lat, lng))
print name
self.location_geo = geo
return Point(geo[1], geo[0])
def get_distance(self):
return D(km=self.request.GET.get('distance', self.distance))
def get_queryset(self):
location = self.get_location()
distance = self.get_distance()
print location, distance
return SearchQuerySet().dwithin('location', location, distance).distance('location', location).order_by('-distance')
def get_context_data(self, **kwargs):
ctx = super(DistanceSearchView, self).get_context_data(**kwargs)
ctx.update({
'location': self.request.GET.get('location'),
'location_geo': self.location_geo,
})
return ctx

View File

@@ -0,0 +1,68 @@
from django.views.generic import ListView, DetailView, UpdateView
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.contrib.formtools.wizard.views import SessionWizardView
from .mixins import EditorCheckMixin, HaystackSearchListMixin
from ..forms import AddressInline, StoreForm, AddressForm
from ..models import Store
class StoreListView(HaystackSearchListMixin, ListView):
model = Store
paginate_by = 10
def get_context_data(self, **kwargs):
ctx = super(StoreListView, self).get_context_data(**kwargs)
search = self.get_search_terms()
if search:
ctx.update({
'search_query': search,
})
return ctx
def get_queryset(self):
qs = super(StoreListView, self).get_queryset()
return qs.filter(active=True).select_related('address')
class StoreDetailView(EditorCheckMixin, DetailView):
model = Store
def get_queryset(self):
qs = super(StoreDetailView, self).get_queryset()
return qs.filter(active=True).select_related('address', 'address__county', 'address__country', 'chain').prefetch_related('brands')
class StoreUpdateView(UpdateView):
model = Store
form_class = StoreForm
def form_valid(self, form):
messages.success(self.request, "%s updated successfully." % self.object)
return super(UpdateView, self).form_valid(form)
class StoreCreateView(SessionWizardView):
form_list = [AddressForm, StoreForm]
def done(self, form_list, **kwargs):
address, store = form_list
addr_obj = address.save(commit=False)
store_obj = store.save(commit=False)
addr_obj.name = store_obj.name
addr_obj.save()
store_obj.address = addr_obj
store_obj.active = False
store_obj.save()
messages.success(self.request, "%s has been sumbitted for moderation and should be visible within the next 24 hours." % store_obj)
return HttpResponseRedirect(reverse('store-map'))
def get_template_names(self):
return 'stores/wizard/store_wizard.html'