diff --git a/cms/models.py b/cms/models.py index 9f803f1..019fb89 100644 --- a/cms/models.py +++ b/cms/models.py @@ -24,10 +24,10 @@ class Post (models.Model): on_delete=models.SET_NULL, blank = True, null = True ) - thread_pk = models.PositiveIntegerField( + thread_id = models.PositiveIntegerField( blank = True, null = True ) - thread = GenericForeignKey('thread_type', 'thread_pk') + thread = GenericForeignKey('thread_type', 'thread_id') published = models.BooleanField( verbose_name = _('public'), @@ -64,9 +64,21 @@ class Post (models.Model): blank = True, ) + @classmethod + def children_of(cl, thread, queryset = None): + """ + Return children of the given thread of the cl's type. If queryset + is not given, use cl.objects as starting queryset. + """ + if not queryset: + queryset = cl.objects + thread_type = ContentType.objects.get_for_model(thread) + qs = queryset.filter(thread_id = thread.pk, + thread_type__pk = thread_type.id) + return qs def detail_url (self): - return reverse(self._meta.verbose_name.lower() + '_detail', + return reverse(self._website.name_of_model(self.__class__) + '_detail', kwargs = { 'pk': self.pk, 'slug': slugify(self.title) }) @@ -145,6 +157,7 @@ class RelatedPostBase (models.base.ModelBase): def __new__ (cl, name, bases, attrs): # TODO: allow proxy models and better inheritance + # TODO: check bindings if name == 'RelatedPost': return super().__new__(cl, name, bases, attrs) @@ -267,18 +280,6 @@ class RelatedPost (Post, metaclass = RelatedPostBase): self.related.save() - @classmethod - def sync_from_rel(cl, rel, save = True): - """ - Update a rel_to_post from a given rel object. Return -1 if there is no - related post to update - """ - self = cl.objects.filter(related = rel) - if not self or not self.count(): - return -1 - self[0].rel_to_post(save) - - def rel_to_post(self, save = True): """ Change the post using the related object bound values. Save the @@ -286,25 +287,30 @@ class RelatedPost (Post, metaclass = RelatedPostBase): Note: does not check if Relation.post_to_rel is True """ rel = self._relation - if rel.bindings: + if not rel.bindings: return + has_changed = False + def set_attr(attr, value): + if getattr(self, attr) != value: + has_changed = True + setattr(self, attr, value) + for attr, rel_attr in rel.bindings.items(): if attr == 'thread': continue self.set_rel_attr - value = getattr(self.related, attr) \ - if hasattr(self.related, attr) else None - setattr(self, attr, value) + value = getattr(self.related, rel_attr) + set_attr(attr, value) if rel.thread_model: thread = self.get_rel_attr('thread') thread = rel.thread_model.objects.filter(related = thread) \ if thread else None thread = thread[0] if thread else None - self.thread = thread + set_attr('thread', thread) - if save: + if has_changed and save: self.save() def __init__ (self, *kargs, **kwargs): @@ -329,10 +335,10 @@ class Comment(models.Model): on_delete=models.SET_NULL, blank = True, null = True ) - thread_pk = models.PositiveIntegerField( + thread_id = models.PositiveIntegerField( blank = True, null = True ) - thread = GenericForeignKey('thread_type', 'thread_pk') + thread = GenericForeignKey('thread_type', 'thread_id') author = models.TextField( verbose_name = _('author'), diff --git a/cms/routes.py b/cms/routes.py index 700c090..fda6e03 100644 --- a/cms/routes.py +++ b/cms/routes.py @@ -3,65 +3,48 @@ from django.contrib.contenttypes.models import ContentType from django.utils import timezone from django.utils.translation import ugettext as _, ugettext_lazy -from website.models import * -from website.views import * - -class Router: - registry = [] - - def register (self, route): - if not route in self.registry: - self.registry.append(route) - - def register_set (self, view_set): - for url in view_set.urls: - self.register(url) - - def unregister (self, route): - self.registry.remove(route) - - def get_urlpatterns (self): - return [ url for url in self.registry ] - class Route: """ Base class for routing. Given a model, we generate url specific for each - route type. The generated url takes this form: - model_name + '/' + route_name + '/' + '/'.join(route_url_args) + type of route. - Where model_name by default is the given model's verbose_name (uses plural if - Route is for a list). + The generated url takes this form: + name + '/' + route_name + '/' + '/'.join(route_url_args) - The given view is considered as a django class view, and has view_ + And their name (to use for reverse: + name + '_' + route_name + + By default name is the verbose name of the model. It is always in + singular form. """ name = None # route name url_args = [] # arguments passed from the url [ (name : regex),... ] @classmethod - def get_queryset (cl, website, model, request, **kwargs): + def get_queryset(cl, website, model, request, **kwargs): """ Called by the view to get the queryset when it is needed """ pass @classmethod - def get_object (cl, website, model, request, **kwargs): + def get_object(cl, website, model, request, **kwargs): """ Called by the view to get the object when it is needed """ pass @classmethod - def get_title (cl, model, request, **kwargs): + def get_title(cl, model, request, **kwargs): return '' @classmethod - def get_view_name (cl, name): + def get_view_name(cl, name): return name + '_' + cl.name @classmethod - def as_url (cl, name, model, view, view_kwargs = None): + def as_url(cl, name, view, view_kwargs = None): pattern = '^{}/{}'.format(name, cl.name) if cl.url_args: url_args = '/'.join([ @@ -84,7 +67,7 @@ class Route: name = cl.get_view_name(name)) -class DetailRoute (Route): +class DetailRoute(Route): name = 'detail' url_args = [ ('pk', '[0-9]+'), @@ -92,25 +75,25 @@ class DetailRoute (Route): ] @classmethod - def get_object (cl, website, model, request, pk, **kwargs): + def get_object(cl, website, model, request, pk, **kwargs): return model.objects.get(pk = int(pk)) -class AllRoute (Route): +class AllRoute(Route): name = 'all' @classmethod - def get_queryset (cl, website, model, request, **kwargs): + def get_queryset(cl, website, model, request, **kwargs): return model.objects.all() @classmethod - def get_title (cl, model, request, **kwargs): + def get_title(cl, model, request, **kwargs): return _('All %(model)s') % { 'model': model._meta.verbose_name_plural } -class ThreadRoute (Route): +class ThreadRoute(Route): """ Select posts using by their assigned thread. @@ -125,7 +108,7 @@ class ThreadRoute (Route): ] @classmethod - def get_queryset (cl, website, model, request, thread_model, pk, **kwargs): + def get_queryset(cl, website, model, request, thread_model, pk, **kwargs): if type(thread_model) is str: thread_model = website.registry.get(thread_model) @@ -139,7 +122,7 @@ class ThreadRoute (Route): ) -class DateRoute (Route): +class DateRoute(Route): name = 'date' url_args = [ ('year', '[0-9]{4}'), @@ -148,7 +131,7 @@ class DateRoute (Route): ] @classmethod - def get_queryset (cl, website, model, request, year, month, day, **kwargs): + def get_queryset(cl, website, model, request, year, month, day, **kwargs): return model.objects.filter( date__year = int(year), date__month = int(month), @@ -156,11 +139,11 @@ class DateRoute (Route): ) -class SearchRoute (Route): +class SearchRoute(Route): name = 'search' @classmethod - def get_queryset (cl, website, model, request, q, **kwargs): + def get_queryset(cl, website, model, request, q, **kwargs): qs = model.objects for search_field in model.search_fields or []: r = model.objects.filter(**{ search_field + '__icontains': q }) diff --git a/cms/static/aircox_cms/styles.css b/cms/static/aircox/cms/styles.css similarity index 100% rename from cms/static/aircox_cms/styles.css rename to cms/static/aircox/cms/styles.css diff --git a/cms/templates/aircox/cms/detail.html b/cms/templates/aircox/cms/detail.html index 2859c4b..dc1d37a 100644 --- a/cms/templates/aircox/cms/detail.html +++ b/cms/templates/aircox/cms/detail.html @@ -1,14 +1,31 @@ {% extends embed|yesno:"aircox/cms/base_content.html,aircox/cms/base_site.html" %} +{% load aircox_cms %} {% block title %} {{ object.title }} {% endblock %} {% block pre_title %} +
+{% if object.thread %} +
+ {{ object|threads:' > '|safe }} +
+{% endif %} + + +{% if object.tags %} +{# TODO: url to the tags #} +
+ {{ object.tags.all|join:', ' }} +
+{% endif %} + +
{% endblock %} {% block content %} diff --git a/cms/templates/aircox/cms/section_list.html b/cms/templates/aircox/cms/section_list.html index f1eb561..c28de59 100644 --- a/cms/templates/aircox/cms/section_list.html +++ b/cms/templates/aircox/cms/section_list.html @@ -5,7 +5,7 @@ {% block section_content %}