Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

It's been long enough, get 0.2 merged and let's focus on getting to 1.0 #1

Merged
merged 15 commits into from
This page is out of date. Refresh to see the latest.
View
3  MANIFEST.in
@@ -1 +1,2 @@
-include README.rst
+include README.rst
+recursive-include boxes/templates *
View
8 boxes/admin.py
@@ -1,6 +1,12 @@
from django.contrib import admin
+import reversion
+
from boxes.models import Box
-admin.site.register(Box)
+class BoxAdmin(reversion.VersionAdmin):
+ search_fields = ["content"]
+
+
+admin.site.register(Box, BoxAdmin)
View
20 boxes/authorization.py
@@ -1,20 +0,0 @@
-from django.conf import settings
-
-from boxes.utils import load_path_attr
-
-
-def default_can_edit(request, *args, **kwargs):
- """
- This is meant to be overridden in your project per domain specific
- requirements.
- """
- return request.user.is_staff
-
-
-def load_can_edit():
- import_path = getattr(settings, "BOXES_CAN_EDIT_CALLABLE", None)
-
- if import_path is None:
- return default_can_edit
-
- return load_path_attr(import_path)
View
3  boxes/models.py
@@ -8,10 +8,11 @@
class Box(models.Model):
label = models.CharField(max_length=100, db_index=True)
- content = models.TextField()
+ content = models.TextField(blank=True)
created_by = models.ForeignKey(User, related_name="boxes")
last_updated_by = models.ForeignKey(User, related_name="updated_boxes")
+ last_updated = models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self):
return self.label
View
26 boxes/templates/boxes/box.html
@@ -0,0 +1,26 @@
+{% load i18n %}
+
+{% if form %}
+ <div id="edit_{{ label }}" class="modal fade hide">
+ <form id="edit_form_{{ label }}" accept-charset="UTF-8" class="modal-form" method="POST" action="{{ form_action }}?next={{ request.path }}">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h3>{% trans "Editing content:" %} {{ label }}</h3>
+ </div>
+ <div class="modal-body">
+ {% csrf_token %}
+ {{ form.content }}
+ </div>
+ <div class="form-actions">
+ <button type="submit" class="btn btn-primary">Save changes</a>
+ </div>
+ </form>
+ </div>
+{% endif %}
+
+<div id="content_{{ label }}" class="content-box {% if form %}editable{% endif %}">
+ {% if form %}
+ <a href="#edit_{{ label }}" data-toggle="modal" class="btn edit-toggle"><i class="icon-pencil"></i> Edit this content</a>
+ {% endif %}
+ {{ box.content|safe }}
+</div>
View
103 boxes/templatetags/boxes_tags.py
@@ -1,94 +1,35 @@
from django import template
-from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse
-from django.utils.safestring import mark_safe
-from django.utils.encoding import smart_str
-from django.utils.translation import ugettext_lazy as _
-from django.template.defaulttags import kwarg_re
from boxes.models import Box
-from boxes.authorization import load_can_edit
+from boxes.forms import BoxForm
register = template.Library()
-class BoxNode(template.Node):
+@register.inclusion_tag("boxes/box.html", takes_context=True)
+def box(context, label, show_edit=True, *args, **kwargs):
- @classmethod
- def handle(cls, parser, token):
- bits = token.split_contents()
- if len(bits) < 2:
- raise template.TemplateSyntaxError(
- "'box' takes at least one argument (label of the content to display)"
- )
- args = []
- kwargs = {}
- label = parser.compile_filter(bits[1])
- bits = bits[2:]
- if len(bits):
- for bit in bits:
- match = kwarg_re.match(bit)
- if not match:
- raise template.TemplateSyntaxError("Malformed arguments to 'box' tag")
- name, value = match.groups()
- if name:
- kwargs[name] = parser.compile_filter(value)
- else:
- args.append(parser.compile_filter(value))
- return cls(label, args, kwargs)
+ request = context["request"]
+ can_edit = request.user.has_perm("boxes.change_box")
- def __init__(self, label, args, kwargs):
- self.label = label
- self.args = args
- self.kwargs = kwargs
+ try:
+ box = Box.objects.get(label=label)
+ except Box.DoesNotExist:
+ box = None
- def render(self, context):
- try:
- request = context["request"]
- except KeyError:
- raise ImproperlyConfigured('django-boxes requires the use of "django.core.context_processors.request" in TEMPLATE_CONTEXT_PROCESSORS')
-
- label = self.label.resolve(context)
- args = [arg.resolve(context) for arg in self.args]
- kwargs = dict([
- (smart_str(k, "ascii"), v.resolve(context))
- for k, v in self.kwargs.items()
- ])
-
- show_edit_link = load_can_edit()(request, *args, **kwargs)
-
- try:
- box = Box.objects.get(label=label)
- content = box.content.strip()
- except Box.DoesNotExist:
- box = None
- content = ""
-
- if len(content) == 0:
- content = _("<p>No content for this box has been created yet.</p>")
-
- # @@@ encode args/kwargs into querystring
- if show_edit_link:
- if box is None:
- url = reverse("box_create", args=[label])
- link_text = unicode(_("Create"))
- else:
- url = reverse("box_edit", args=[box.pk])
- link_text = unicode(_("Edit"))
-
- content += " <a href=\"%s\" class=\"boxes-edit-link\" rel=\"facebox\">%s</a>" % (url, link_text)
-
- return mark_safe(content)
-
-
-@register.tag
-def box(parser, token):
- """
- {% box label [args] [kwargs] %}
+ if can_edit and show_edit:
+ form = BoxForm(instance=box, prefix=label)
+ form_action = reverse("box_edit", args=[label])
+ else:
+ form = None
+ form_action = None
- All args/kwargs are passed directly to callable defined in the setting
- BOXES_CAN_EDIT_CALLABLE which returns True or False to determine if the
- box can be edited.
- """
- return BoxNode.handle(parser, token)
+ return {
+ "request": request,
+ "label": label,
+ "box": box,
+ "form": form,
+ "form_action": form_action,
+ }
View
5 boxes/urls.py
@@ -2,6 +2,5 @@
urlpatterns = patterns("boxes.views",
- url(r"^([-\w]+)/create/$", "box_create", name="box_create"),
- url(r"^(\d+)/edit/$", "box_edit", name="box_edit"),
-)
+ url(r"^([-\w]+)/edit/$", "box_edit", name="box_edit"),
+)
View
19 boxes/utils.py
@@ -1,19 +0,0 @@
-from django.core.exceptions import ImproperlyConfigured
-try:
- from django.utils.importlib import import_module
-except ImportError:
- from importlib import import_module
-
-
-def load_path_attr(path):
- i = path.rfind(".")
- module, attr = path[:i], path[i+1:]
- try:
- mod = import_module(module)
- except ImportError, e:
- raise ImproperlyConfigured("Error importing %s: '%s'" % (module, e))
- try:
- attr = getattr(mod, attr)
- except AttributeError:
- raise ImproperlyConfigured("Module '%s' does not define a '%s'" % (module, attr))
- return attr
View
90 boxes/views.py
@@ -1,61 +1,51 @@
-from django.http import HttpResponseForbidden
-from django.shortcuts import get_object_or_404, render_to_response
+import datetime
+import json
+
+from django.core.urlresolvers import reverse
+from django.http import HttpResponse, HttpResponseForbidden
+from django.shortcuts import redirect
from django.template import RequestContext
+from django.template.loader import render_to_string
+from django.views.decorators.http import require_POST
-from boxes.authorization import load_can_edit
from boxes.forms import BoxForm
from boxes.models import Box
-# @@@ problem with this is that the box_edit.html and box_create.html won't have domain objects in context
-def get_auth_vars(request):
- auth_vars = {}
- if request.method == "POST":
- keys = [k for k in request.POST.keys() if k.startswith("boxes_auth_")]
- for key in keys:
- auth_vars[key.replace("boxes_auth_", "")] = request.POST.get(key)
- auth_vars["user"] = request.user
- return auth_vars
-
-
-def box_edit(request, pk):
- box = get_object_or_404(Box, pk=pk)
- if request.method == "POST":
- #if not load_can_edit()(request, **get_auth_vars(request)):
- # return HttpResponseForbidden()
-
- form = BoxForm(request.POST, instance=box)
- if form.is_valid():
- form.save()
- return render_to_response("boxes/refresh.html", {})
- else:
- form = BoxForm(instance=box)
- ctx = {
- "form": form,
- "box": box,
- }
- ctx = RequestContext(request, ctx)
- return render_to_response("boxes/box_edit.html", ctx)
-
-
-def box_create(request, label):
- if request.method == "POST":
- #if not load_can_edit()(request, **get_auth_vars(request)):
- # return HttpResponseForbidden()
-
- form = BoxForm(request.POST)
- if form.is_valid():
+@require_POST
+def box_edit(request, label):
+
+ if not request.user.has_perm("boxes.change_box"):
+ return HttpResponseForbidden()
+
+ next = request.GET.get("next")
+
+ try:
+ box = Box.objects.get(label=label)
+ except Box.DoesNotExist:
+ box = None
+
+ form = BoxForm(request.POST, instance=box, prefix=label)
+
+ if form.is_valid():
+ if box is None:
box = form.save(commit=False)
box.label = label
box.created_by = request.user
box.last_updated_by = request.user
+ box.last_updated = datetime.datetime.now()
box.save()
- return render_to_response("boxes/refresh.html", {})
- else:
- form = BoxForm()
- ctx = {
- "form": form,
- "label": label
- }
- ctx = RequestContext(request, ctx)
- return render_to_response("boxes/box_create.html", ctx)
+ else:
+ form.save()
+
+ if request.is_ajax():
+ data = {
+ "html": render_to_string("boxes/box.html", {
+ "label": label,
+ "form": BoxForm(instance=box, prefix=label),
+ "box": box,
+ "form_action": reverse("box_edit", args=[label])
+ }, context_instance=RequestContext(request))
+ }
+ return HttpResponse(json.dumps(data), mimetype="application/json")
+ return redirect(next)
View
5 setup.py
@@ -3,13 +3,16 @@
setup(
name = "django-boxes",
- version = "1.0b1.dev2",
+ version = "2.0b1.dev1",
author = "Eldarion",
author_email = "development@eldarion.com",
description = "a reusable Django content-boxes application",
long_description = open("README.rst").read(),
license = "BSD",
url = "http://github.com/eldarion/boxes",
+ install_requires = [
+ "django-reversion",
+ ],
packages = [
"boxes",
"boxes.templatetags",
Something went wrong with that request. Please try again.