This is a simplest approach possible. `as_view()` is replaced, so
that it applies the given decorator before returning.
In this approach, decorators are always put on top - that means it's not
possible to have functions called in this order:
B.dispatch, login_required, A.dispatch
NOTE: By default this modifies the given class, so be careful when doing this:
TemplateView = view_decorator(login_required)(TemplateView)
Because it will modify the TemplateView class. Instead create a fresh
class first and apply the decorator there. A shortcut for this is
specifying the ``subclass`` argument. But this is also dangerous. Consider:
@view_decorator(login_required, subclass=True)
class MyView(View):
def get_context_data(self):
data = super(MyView, self).get_context_data()
data["foo"] = "bar"
return data
This looks like a normal Python code, but there is a hidden infinite
recursion, because of how `super()` works in Python 2.x; By the time
`get_context_data()` is invoked, MyView refers to a subclass created in
the decorator. super() looks at the next class in the MRO of MyView,
which is the original MyView class we created, so it contains the
`get_context_data()` method. Which is exactly the method that was just
called. BOOM!
- decorator
- class-based-views
- decorating
- cbv
I couldn't find any code for a blog-style "Read more after the jump," so I made a custom filter. It will look for **<!--more-->** for the jump, like in Wordpress.
In **settings.py** set **READ_MORE_TEXT** to what you want the text of the link to be.
`READ_MORE_TEXT = 'Read more after the jump.'`
When you call the filter in your template, pass it the absolute link of that entry. Of course, you have to have your **get_absolute_url** function defined in your model, but you should have that already, right? :P
In this example **entry.body** is the content of the blog entry.
`{% load blog_filters %}`
`{{ entry.body|read_more:entry.get_absolute_url }}`
If anyone has a better way to do this, it is, of course, welcome.
- template
- filter
- blog
- find
- jump
- read
- more
I know you're thinking, *what the heck could that title mean?*
I often find myself wanting to filter and order by the result of a COUNT(*) of a query using a method similar to the [entry_count example](http://www.djangoproject.com/documentation/db-api/#extra-select-none-where-none-params-none-tables-none). Writing this many times is tedious and hardcoding the table and column names made me cringe, I also wanted the counts to result from more complex queries.
This is a method you can add to your custom Manager to do this easily. It's not an ideal syntax, but it's good for the amount of code required.
Example: suppose we have some articles we want to filter and order by comments and visit logs to show the most popular...
class ArticleManager(models.Manager):
count_related = _count_related
class Article(models.Model):
pub_date = models.DateTimeField(auto_now_add=True)
objects = ArticleManager()
class Comment(models.Model):
article = models.ForeignKey(Article)
is_spam = models.BooleanField(default=False)
class Visit(models.Model):
article = models.ForeignKey(Article)
referrer = models.URLField(verify_exists=False)
search_query = models.CharField(maxlength=200)
Notice how the ArticleManager is given the `count_related` method. Now you can find the most popular like so...
Order by non-spam comments:
Article.objects.count_related(Comment.objects.filter(
is_spam=False)).order_by('-comment__count')
Order by incoming non-search-engine links:
Article.objects.count_related(Visit.objects.filter(
referrer__isnull=False, search_query__isnull=True),
'links').order_by('-links')
Order by total visits:
Article.objects.count_related(Visit).order_by('-visit__count')
Note: Doesn't work if `query` contains joins or for many-to-many relationships, but those could be made to work identically if there's demand.
- sql
- model
- db
- count
- manager