diff --git a/app/stores/admin.py b/app/stores/admin.py index ba87cd8..29e458e 100644 --- a/app/stores/admin.py +++ b/app/stores/admin.py @@ -4,6 +4,7 @@ from django.shortcuts import render_to_response from django import forms from django.db import transaction from django.db.models import Count +from django.utils.timezone import now from django.contrib import admin from django.contrib.contenttypes.generic import GenericStackedInline from .models import Chain, Store, Address, Brand, ClaimRequest, Link, LinkType, County, Country @@ -16,7 +17,7 @@ class LinkInlineAdmin(GenericStackedInline): class ChainAdmin(admin.ModelAdmin): list_filter = ['active'] - list_display = ['name'] + list_display = ['name', 'active', 'changed'] prepopulated_fields = {"slug": ("name",)} search_fields = ['name'] inlines = [ @@ -25,7 +26,7 @@ class ChainAdmin(admin.ModelAdmin): class StoreAdmin(admin.ModelAdmin): list_filter = ['chain', 'active'] - list_display = ['name', 'store_type', 'active'] + list_display = ['name', 'store_type', 'active', 'changed'] prepopulated_fields = {"slug": ("name",)} search_fields = ['name'] inlines = [ @@ -39,7 +40,7 @@ class StoreAdmin(admin.ModelAdmin): def set_active(self, request, queryset): with transaction.commit_on_success(): - queryset.update(active=True) + queryset.update(active=True, changed=now()) self.message_user(request, "Successfully set %d stores to active." % queryset.count()) set_active.short_description = 'Set selected stores active.' @@ -53,6 +54,7 @@ class StoreAdmin(admin.ModelAdmin): with transaction.commit_on_success(): for store in queryset: store.brands.add(brand) + queryset.update(changed=now()) if count > 1: plural = 's' else: @@ -61,7 +63,7 @@ class StoreAdmin(admin.ModelAdmin): return HttpResponseRedirect(request.get_full_path()) if not form: form = self.AddBrandForm(initial={'_selected_action': queryset.values_list('id', flat=True)}) - return render_to_response('admin/add_brand.html', {'stores': queryset, 'brand_form': form }, RequestContext(request)) + return render_to_response('admin/add_brand.html', {'stores': queryset, 'brand_form': form}, RequestContext(request)) add_brand.short_description = "Add brand to the selected stores" @@ -77,9 +79,7 @@ class StoreAdmin(admin.ModelAdmin): count = queryset.count() chain = form.cleaned_data['chain'] with transaction.commit_on_success(): - for store in queryset: - store.chain = chain - store.save() + queryset.update(chain=chain, changed=now()) if count > 1: plural = 's' else: @@ -101,12 +101,13 @@ class ClaimAdmin(admin.ModelAdmin): def approve_request(self, request, queryset): qs = queryset.filter(status=ClaimRequest.CLAIM_STATUS_PENDING) - for obj in qs: - obj.status = ClaimRequest.CLAIM_STATUS_APPROVED - target = obj.generic_obj - target.editor = obj.user - target.save() - obj.save() + with transaction.commit_on_success(): + for obj in qs: + obj.status = ClaimRequest.CLAIM_STATUS_APPROVED + target = obj.generic_obj + target.editor = obj.user + target.save() + obj.save() if qs.count() == 1: message_bit = "1 request was" else: @@ -139,9 +140,7 @@ class CountyAdmin(admin.ModelAdmin): if form.is_valid(): country = form.cleaned_data['country'] with transaction.commit_on_success(): - for county in queryset: - county.country = country - county.save() + queryset.update(country=country) self.message_user(request, "Successfully set %d counties to %s." % (queryset.count(), country)) return HttpResponseRedirect(request.get_full_path()) if not form: diff --git a/app/stores/migrations/0011_auto__add_field_chain_created__add_field_chain_changed__add_field_stor.py b/app/stores/migrations/0011_auto__add_field_chain_created__add_field_chain_changed__add_field_stor.py new file mode 100644 index 0000000..b387163 --- /dev/null +++ b/app/stores/migrations/0011_auto__add_field_chain_created__add_field_chain_changed__add_field_stor.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +from django.utils.timezone import now +from south.db import db +from south.v2 import SchemaMigration + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Chain.created' + db.add_column(u'stores_chain', 'created', + self.gf('django.db.models.fields.DateTimeField')(default=now), + keep_default=False) + + # Adding field 'Chain.changed' + db.add_column(u'stores_chain', 'changed', + self.gf('django.db.models.fields.DateTimeField')(default=now), + keep_default=False) + + # Adding field 'Store.created' + db.add_column(u'stores_store', 'created', + self.gf('django.db.models.fields.DateTimeField')(default=now), + keep_default=False) + + # Adding field 'Store.changed' + db.add_column(u'stores_store', 'changed', + self.gf('django.db.models.fields.DateTimeField')(default=now), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Chain.created' + db.delete_column(u'stores_chain', 'created') + + # Deleting field 'Chain.changed' + db.delete_column(u'stores_chain', 'changed') + + # Deleting field 'Store.created' + db.delete_column(u'stores_store', 'created') + + # Deleting field 'Store.changed' + db.delete_column(u'stores_store', 'changed') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'stores.address': { + 'Meta': {'object_name': 'Address'}, + 'address1': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'address2': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'address3': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': "'50'"}), + 'country': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'addresses'", 'to': "orm['stores.Country']"}), + 'county': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'addresses'", 'null': 'True', 'to': "orm['stores.County']"}), + 'geo_latitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'geo_longitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}) + }, + 'stores.brand': { + 'Meta': {'ordering': "['name']", 'object_name': 'Brand'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + }, + 'stores.chain': { + 'Meta': {'ordering': "['name']", 'object_name': 'Chain'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'changed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'editable_chains'", 'null': 'True', 'to': u"orm['auth.User']"}), + 'head_office': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stores.Address']", 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'long_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'blank': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + }, + 'stores.claimrequest': { + 'Meta': {'object_name': 'ClaimRequest'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'note': ('django.db.models.fields.TextField', [], {}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'object_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claims'", 'to': u"orm['auth.User']"}) + }, + 'stores.country': { + 'Meta': {'ordering': "['name']", 'object_name': 'Country'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iso_code': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'stores.county': { + 'Meta': {'ordering': "['name']", 'object_name': 'County'}, + 'country': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'counties'", 'null': 'True', 'to': "orm['stores.Country']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'stores.link': { + 'Meta': {'object_name': 'Link'}, + 'account_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'account_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['stores.LinkType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'object_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}) + }, + 'stores.linktype': { + 'Meta': {'ordering': "['name']", 'object_name': 'LinkType'}, + 'icon': ('django.db.models.fields.CharField', [], {'default': "'icon-globe'", 'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'url_format': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'stores.store': { + 'Meta': {'ordering': "['name']", 'object_name': 'Store'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'address': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stores'", 'to': "orm['stores.Address']"}), + 'brands': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'stores'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['stores.Brand']"}), + 'chain': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'stores'", 'null': 'True', 'to': "orm['stores.Chain']"}), + 'changed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'editable_stores'", 'null': 'True', 'to': u"orm['auth.User']"}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'long_description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'phone': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'blank': 'True'}), + 'store_type': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['stores'] \ No newline at end of file diff --git a/app/stores/models/base.py b/app/stores/models/base.py index f210a1b..d3fc6c6 100644 --- a/app/stores/models/base.py +++ b/app/stores/models/base.py @@ -1,6 +1,7 @@ import re from django.db import models from django.core.urlresolvers import reverse_lazy +from django.utils.timezone import now from django.contrib.auth import get_user_model from django.contrib.gis.geos import Point from django.contrib.contenttypes.models import ContentType @@ -21,9 +22,13 @@ class Chain(models.Model): long_description = models.TextField('Description', null=True, blank=True) links = generic.GenericRelation('stores.Link', content_type_field='object_type') + created = models.DateTimeField('Created Date/Time', default=now) + changed = models.DateTimeField('Changed Date/Time', default=now) + def save(self, **kwargs): if self.slug == '': self.slug = re.sub(r'\W+', '-', str(self.name).lower()) + self.changed = now() return super(Chain, self).save(**kwargs) def get_absolute_url(self): @@ -65,6 +70,9 @@ class Store(models.Model): long_description = models.TextField('Description', null=True, blank=True, help_text="Full description of the store, including any marketing material. Markdown supported.") brands = models.ManyToManyField('stores.Brand', related_name='stores', null=True, blank=True, help_text="Brands that are sold by this store.") + created = models.DateTimeField('Created Date/Time', default=now) + changed = models.DateTimeField('Changed Date/Time', default=now) + def get_full_address(self): if self.address: return self.address.full_address @@ -76,6 +84,7 @@ class Store(models.Model): def save(self, **kwargs): if not self.slug or self.slug == '': self.slug = re.sub(r'\W+', '-', str(self.name).lower()) + self.changed = now() return super(Store, self).save(**kwargs) def get_absolute_url(self): diff --git a/app/stores/templates/stores/store_detail.html b/app/stores/templates/stores/store_detail.html index c67e57b..f84eef9 100644 --- a/app/stores/templates/stores/store_detail.html +++ b/app/stores/templates/stores/store_detail.html @@ -9,7 +9,7 @@ {% block style %}