summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2018-03-13 11:19:31 -0500
committerluxagraf <sng@luxagraf.net>2018-03-13 11:19:31 -0500
commitab62d6af3ed33234f0ab849ef5d5c3b5a400f6e3 (patch)
treeb4aa8932a4dffeaba89dfaa74e0d0fae61785ec2 /app
parentce9c1a25a2872979b969c64f804529d200a8c0ad (diff)
fixed an ordering bug in sightings AP
Diffstat (limited to 'app')
-rw-r--r--app/sightings/models.py63
-rw-r--r--app/utils/next_prev.py80
2 files changed, 129 insertions, 14 deletions
diff --git a/app/sightings/models.py b/app/sightings/models.py
index 80b9ba9..8531772 100644
--- a/app/sightings/models.py
+++ b/app/sightings/models.py
@@ -1,15 +1,25 @@
import datetime
+import re
from django.urls import reverse
from django.apps import apps
from django.template.defaultfilters import slugify
from django.contrib.gis.db import models
-from django.contrib.auth.models import User
+# from django.contrib.auth.models import User
from django.utils import timezone
-from locations.models import Location
from django import forms
from django.conf import settings
-from photos.models import LuxImage
+# from photos.models import LuxImage
+
+from locations.models import Location
+from utils.widgets import parse_image
+from utils.widgets import markdown_to_html
+from utils.next_prev import next_in_order, prev_in_order
+
+
+def render_images(s):
+ s = re.sub('<img(.*)/>', parse_image, s)
+ return s
def get_upload_path(self, filename):
@@ -48,6 +58,7 @@ class APClass(models.Model):
def __str__(self):
return self.common_name
+
class AP(models.Model):
common_name = models.CharField(max_length=200)
slug = models.SlugField()
@@ -56,8 +67,13 @@ class AP(models.Model):
apclass = models.ForeignKey(APClass, on_delete=models.CASCADE)
body_html = models.TextField(null=True, blank=True)
body_markdown = models.TextField(null=True, blank=True)
- #image = models.FileField(upload_to=get_upload_path, null=True, blank=True, help_text="width of high res is 1360px")
- #image_credit = models.CharField(max_length=200, blank=True, null=True)
+ # image = models.FileField(upload_to=get_upload_path, null=True, blank=True, help_text="width of high res is 1360px")
+ # image_credit = models.CharField(max_length=200, blank=True, null=True)
+
+ class Meta:
+ verbose_name_plural = 'Animal/Plant'
+ verbose_name = 'Animal/Plant'
+ ordering = ["common_name", ]
def __str__(self):
return self.common_name
@@ -71,10 +87,29 @@ class AP(models.Model):
def kind(self):
return self.apclass.kind
- class Meta:
- verbose_name_plural = 'Animal/Plant'
- verbose_name = 'Animal/Plant'
- ordering = ["common_name", ]
+ def get_prev(self):
+ model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name)
+ return prev_in_order(self, model.objects.all())
+
+ def get_next(self):
+ model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name)
+ return next_in_order(self, model.objects.all())
+
+ @property
+ def get_previous_admin_url(self):
+ model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name)
+ try:
+ return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[self.get_prev().pk])
+ except model.DoesNotExist:
+ return ''
+
+ @property
+ def get_next_admin_url(self):
+ model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name)
+ try:
+ return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[self.get_next().pk])
+ except model.DoesNotExist:
+ return ''
def save(self, *args, **kwargs):
if self.pk:
@@ -89,9 +124,9 @@ class Sighting(models.Model):
point = models.PointField(blank=True)
location = models.ForeignKey(Location, on_delete=models.CASCADE, blank=True)
pub_date = models.DateTimeField('Date', default=timezone.now)
- #seen_by = models.ManyToManyField(User)
- #images = models.ManyToManyField(LuxImage, blank=True)
- #audio = models.ManyToManyField(BirdAudio, blank=True)
+ # seen_by = models.ManyToManyField(User)
+ # images = models.ManyToManyField(LuxImage, blank=True)
+ # audio = models.ManyToManyField(BirdAudio, blank=True)
class Meta:
ordering = ["-pub_date", ]
@@ -122,13 +157,13 @@ class Sighting(models.Model):
@property
def get_previous_admin_url(self):
n = self.get_previous_by_pub_date()
- return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[n.id] )
+ return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[n.id])
@property
def get_next_admin_url(self):
model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name)
try:
- return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[self.get_next_by_pub_date().pk] )
+ return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[self.get_next_by_pub_date().pk])
except model.DoesNotExist:
return ''
diff --git a/app/utils/next_prev.py b/app/utils/next_prev.py
new file mode 100644
index 0000000..766add1
--- /dev/null
+++ b/app/utils/next_prev.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+# from https://github.com/gregplaysguitar/django-next-prev/blob/master/next_prev.py
+
+from functools import partial
+
+from django.db import models
+
+if not locals().get('reduce'):
+ from functools import reduce
+
+__version__ = '1.0.1'
+VERSION = tuple(map(int, __version__.split('.')))
+
+
+def get_model_attr(instance, attr):
+ """Example usage: get_model_attr(instance, 'category__slug')"""
+ for field in attr.split('__'):
+ instance = getattr(instance, field)
+ return instance
+
+
+def next_or_prev_in_order(instance, qs=None, prev=False, loop=False):
+ """Get the next (or previous with prev=True) item for instance, from the
+ given queryset (which is assumed to contain instance) respecting
+ queryset ordering. If loop is True, return the first/last item when the
+ end/start is reached. """
+
+ if not qs:
+ qs = instance.__class__.objects.all()
+
+ if prev:
+ qs = qs.reverse()
+ lookup = 'lt'
+ else:
+ lookup = 'gt'
+
+ q_list = []
+ prev_fields = []
+
+ if qs.query.extra_order_by:
+ ordering = qs.query.extra_order_by
+ elif qs.query.order_by:
+ ordering = qs.query.order_by
+ elif qs.query.get_meta().ordering:
+ ordering = qs.query.get_meta().ordering
+ else:
+ ordering = []
+
+ ordering = list(ordering)
+
+ # if the ordering doesn't contain pk, append it and reorder the queryset
+ # to ensure consistency
+ if 'pk' not in ordering and '-pk' not in ordering:
+ ordering.append('pk')
+ qs = qs.order_by(*ordering)
+
+ for field in ordering:
+ if field[0] == '-':
+ this_lookup = (lookup == 'gt' and 'lt' or 'gt')
+ field = field[1:]
+ else:
+ this_lookup = lookup
+ q_kwargs = dict([(f, get_model_attr(instance, f))
+ for f in prev_fields])
+ key = "%s__%s" % (field, this_lookup)
+ q_kwargs[key] = get_model_attr(instance, field)
+ q_list.append(models.Q(**q_kwargs))
+ prev_fields.append(field)
+ try:
+ return qs.filter(reduce(models.Q.__or__, q_list))[0]
+ except IndexError:
+ length = qs.count()
+ if loop and length > 1:
+ # queryset is reversed above if prev
+ return qs[0]
+ return None
+
+
+next_in_order = partial(next_or_prev_in_order, prev=False)
+prev_in_order = partial(next_or_prev_in_order, prev=True)