Reputation: 930
I have faced one problem in django views. I'm getting categories for my menu, like:
args['categs'] = ArticleCategory.objects.filter(category_language=4).order_by('id')
so let's say, I have
And so on...
And the problem is that I have to write:
args['categs'] = ArticleCategory.objects.filter(category_language=4).order_by('id')
for all views and if I exclude some categories from this list then I have to make changes for all views
How can I use args once for all views?
Upvotes: 1
Views: 75
Reputation: 442
Believe, there are 3 things that can be improved:
Move filter() logic to the appropriate Manager method:
class ArticleCategoryManager(models.Manager):
def menu_categories(self, model, language = 4):
return self.filter(category_language=language).order_by('id')
class ArticleCategory(models.Model):
object = ArticleCategoryManager()
To use default language id:
args['categs'] = ArticleCategory.objects.menu_categories()
To explicitly set language:
args['categs'] = ArticleCategory.objects.menu_categories(language=4)
Replace 4 with a constant: it difficult to read such code & you have to spend some time to understand the meaning of this value.
Example of implementation:
class ArticleCategoryLanguage(object):
GERMAN = 3
ENGLISH = 4
LANGUAGES = (
(GERMAN, 'German'),
(ENGLISH, 'English')
)
Usage:
args['categs'] = ArticleCategory.objects.menu_categories(language=ArticleCategoryLanguage.ENGLISH)
Upvotes: 0
Reputation: 33548
Because this is related with filtering categories in database, you can just extend your ArticleCategory
model manager:
from django.db import models
class ArticleCategoryManager(models.Manager):
def for_menu(self, model):
return self.filter(category_language=4).order_by('id')
class ArticleCategory(models.Model):
objects = ArticleCategoryManager()
Then you will need only to write:
args['categs'] = ArticleCategory.objects.for_menu()
and don't care about how they are actually retrieved. If you need to change the logic of getting them - you change it only in one place - in manager's method.
As about repeated arguments - I don't see a problem in it because there is only one argument and three views, in case of bigger amount use a mixin or helper method to get that set of arguments.
P.S. A little recommendation - do not use hardcoded magic numbers, like 4
, use constants instead.
Upvotes: 0
Reputation: 2000
If you would like to make your categories available in templates, then I'd recommend using a ContextProcessor for that: See Dajgno Documention
However, if you would like to just include them in all your views for some other reason, then I'd use a mixin. See Django Documentation again
Here is a sample mixin I that inherit in all of my views:
class BlogPostMixin(View):
"""
A mixin that renders BlogPost form on GET request and processes it on POST request.
"""
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
""" this is fired up first regardless of what http method is used """
return super(BlogPostMixin, self).dispatch(*args, **kwargs)
def get_context_data(self, **kwargs):
#context = RequestContext(self.request)
context = super(BlogPostMixin, self).get_context_data(**kwargs)
try:
context['form'] = kwargs['form']
context['attachment_form'] = kwargs['attachments_formset']
context['attachment_helper'] = AttachmentFormsetHelper()
except Exception as e:
pass
return context
I use this mixin in my view like:
class BlogPostUpdateView(BlogPostMixin, UpdateView):
"""
A view that updates existing blogposts. The form_valid and form_invalid methods
are handled in in BlogPostMixin because that code is shared between this view and
the CreateView for blogpost.
"""
model = BlogPost
form_class = BlogPostForm
template_name = 'blog/blogpost_form.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(BlogPostUpdateView, self).get(request, *args, **kwargs)
Upvotes: 1