Django: Menu Controller - python

I have a question regarding Django. I created a site and everything works as it is indented to work. The only problem I have is that first of all my urls.py and views.py files are getting quite bloated (I have one method for every page I have) and that i have for every site one template. I use {% extend basetemplate.html %} for making it at least a bit generic. However I find this attempt not really nice. Creating a method inside the urls.py and views.py in addition to create a template html file seems the wrong attempt.
I already thought about building a big controller and did some googleing but i could not find what i was looking for.
Is there something like a best practice to achieve that? How do you guys handle the amount of templates?
Any advice would be more than welcome :)

One solution is to refactor your one application into multiple applications inside your project. Each would have its own urls.py & views.py.

If all your view does is render a template, then you can use TemplateView directly in your urls.py, and you don't need to define a view for each url.
from django.conf.urls import url
from django.views.generic import TemplateView
urlpatterns = [
url(r'^about/', TemplateView.as_view(template_name="about.html"), name="about"),
url(r'^contact/', TemplateView.as_view(template_name="contact.html"), name="contact"),
]
Other generic class based views might be useful as well. If there was a way to map the urls to the template names programatically (e.g. the template name was <slug>.html, you might not even need a url for each template. However, as I said in the comments above, I can't make any specific suggestions without seeing more of your code.

Create a directory called views with the following structure.
.../project/views/
.../project/views/__init__.py
.../project/views/feature_one.py
.../project/views/feature_two.py
.../project/views/feature_three.py
# in .../project/views/__init__.py import the others
from .feature_one import *
from .feature_tow import *
from .feature_threee import *
Now you can go on and import like before from your views. You can do the same thing for admin, models, form ..etc.
For templates, break them up, use inclusion tag to include the smaller partial files. Group them and create a nice directory structure.

Related

Django admin global implicit filter passed as URL part

I want to implement a feature, similar to the one described in "company-goggles" question. Its answers suggest putting the value to filter against into user session, but I really dislike that and try to make it a part of URL instead.
To do this, I want to map any URL admin/company/*/ to just admin/, so I would be able to extract that value later in my admin.py models to apply the queryset filter against it.
Unfortunately, my naive attempts to play with the URL routers failed. The following doesn't seem to work:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/company/\w+/', admin.site.urls),
url(r'^admin/', admin.site.urls),
]
If I remove the second patterns, admin panel got at least displayed, but it reverses all links to admin/company/x/..., and I really have no idea where it takes that "x" from. Trying using include(admin.site.urls) with or withoutnamespace` parameter doesn't help either.
Is there a way to make link reverse work correctly?
Or may there be a conceptually better way to handle this issue?

Which approach to use for customizing django-registration-redux

The first thing I did was of course customizing forms, views and templates in site-packages. And then I learned that everything will be reset to default after upgrading the package.
So now I decided to create a new application "accounts" and make customizations there.
My question is which approach is better (haven't tried any, sorry)
First approach:
Set INCLUDE_REGISTER_URL = False
in accounts.views import RegistrationView and create MyRegistrationView (same thing with forms)
in accounts.urls include registration.backends.default.urls and create my own urlpattern for MyRegistrationView
create custom templates in templates/registration
put registration above django.contrib.admin in INSTALLED_APPS
Second approach:
in accounts.views import RegistrationView and create MyRegistrationView (same thing with forms)
Create complete replica of registration.backends.default.urls in accounts.urls with my new custom template names
put custom templates inside my accounts app
Or are there any better approaches? (probably are)
First of all, if you want to override almost every part of redux, wont it be better to use built-in django authentication and to extend it as you wish?
Yes, you are on the right way. You need to override those things you do not like by coping them to your project and then by changing the copy. Though it's will be a cleaner code if you place templates in templates/registration, views in views.py and etc, actually you can do in some other way you wish.

Django Class Based Views - is it bad style to put all code in urls.py?

Just working through some CBV work, and was wondering if this is bad style. Normally you have a class in your views.py and a URL in urls.py for that view. Something like:
views.py
from django.views.generic.list import ListView
from project.models import Contact
class ContactList(ListView):
model = Contact
urls.py
from django.views.generic.list import ListView
from project.views import ContactList
urlpatterns = [
url(r'contacts/$', ContactList.as_view()),
]
and then a template to show the data.
But, what about just skipping the view code entirely and doing it all like this within the urls.py file:
from django.views.generic.list import ListView
from project.models import Contact
urlpatterns = [
url(r'contacts/$', ListView.as_view(model=Contact)),
]
Is that bad style to group it all into the urls.py file? I mean, it gets rid of excess code inside views.py so isn't that good? Or is this a reduction at the expense of clarity?
It is much more better to keep view logic out of URLConfs.
At a glance url(r'contacts/$', ListView.as_view(model=Contact)) might seem okay, but actually it violates the Django design philosophies:
Loose coupling between urls, views, models has been replaced with tight one, so now you can't reuse your view.
Flexibility of URLs is destroyed. Inheritance, the main advantage of CBV is impossible using them in URLs.
Many other things, for example what if you want to add authentication? Authorization? You will need to wrap all these in decorators and your URLs will quickly become messy.
So:
Views modules should contain view logic.
URL modules should contain URL logic.
The answer is: it depends.
If you're writing a really small app that, you know, won't get bigger, then it doesn't matter, unless you can't resist code smells, you can actually write your whole app in just one file, check answers to this SO question for example How do I write a single-file Django application?
P.S: This problem is universal and is in no way Django specific.
Well, "reducing excess code in views.py" is certainly not a reason. If you're going to instanciate generic views with a couple of simple arguments, you can keep it in urls.py, as long as it works for you. When it doesn't work anymore, maybe move it to views.py or make views a module and move it to views/someview.py, it doesn't matter.

Django: Is there a way to set global views? For example enable data for a sidebar through all URLS

I am building a Django application that is a pretty basic blog, so far it has been wonderful. I got comments, tags etc up. But one thing is bugging me: I cant get the sidebar i want to work. I use the django.views.generic.date_based generic view and this is my urls.py for the blog:
urlpatterns = patterns('django.views.generic.date_based',
(r'(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', 'object_detail',dict(info_dict, slug_field='slug',template_name='blog/detail.html')),
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>w{1,2})/(?P<slug>[-\w]+)/$', 'object_detail', dict(info_dict, template_name='blog/list.html')),
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>w{1,2})/$','archive_day',dict(info_dict,template_name='blog/list.html')),
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month', dict(info_dict, template_name='blog/list.html')),
(r'^(?P<year>\d{4})/$','archive_year', dict(info_dict, template_name='blog/list.html')),
(r'^$','archive_index', dict(info_dict, template_name='blog/list.html')),
)
When i use the URL with 'archive_index' passed i can easily print the latest entries for my sidebar, but when i enter a post i will use one of the top ones where only "object_detail" is availabe. This makes my sidebar entries dissapear. What is the best solution to this problem? Is there a way to make some objects available globally? Through views or otherwise.
People do things like that with template tags. The documentation for custom template tags might be helpful, and there's also a great little tutorial here.
Alternatively, you can use context processors - but that adds an overhead to every single request, which may not be necessary.

Reusing a Django app within a single project

In trying to save as much time as possible in my development and make as many of my apps as reusable as possible, I have run into a bit of a roadblock. In one site I have a blog app and a news app, which are largely identical, and obviously it would be easier if I could make a single app and extend it where necessary, and then have it function as two separate apps with separate databases, etc.
To clarify, consider the following: hypothetically speaking, I would like to have a single, generic news_content app, containing all the relevant models, views, url structure and templatetags, which I could then include and extend where necessary as many times as I like into a single project.
It breaks down as follows:
news_content/
templatetags/
__init__.py
news_content.py
__init__.py
models.py (defines generic models - news_item, category, etc.)
views.py (generic views for news, archiving, etc.)
urls.py
admin.py
Is there a way to include this app multiple times in a project under various names? I feel like it should be obvious and I'm just not thinking clearly about it. Does anybody have any experience with this?
I'd appreciate any advice people can give. Thank you.
What's the actual difference between blogs and news? Perhaps that difference ought to be part of the blog/news app and you include it just once.
If you have a blog page with blog entries and a news page with news entries and the only difference is a field in the database (kind_of_item = "blog" vs. kind_of_item = "news") then perhaps have you have this.
urls.py
(r'^/(?P<kind>blog)/$', 'view.stuff'),
(r'^/(?P<kind>news)/$', 'view.stuff'),
views.py
def stuff( request, kind ):
content= news_blog.objects.filter( kind=kind )
return render_to_response( kind+"_page", { 'content': content } )
Perhaps you don't need the same app twice, but need to extend the app to handle both use cases.
In this case you could create the common piece of code as a Python module instead of a whole new application.
Then for each instance you would like to use it, create an app and import the bits from that module.
I'm not 100% sure I understand your question, so I'm going to list my understanding, and let me know if it is different from yours.
You want to have a "news" and a "blog" section of your website with identical functionality.
You want to have "news" and "blog" entries stored separately in the database so they don't end up intermingling.
If this is the case, I'd suggest making an API to your views. Something like this:
views.py:
def view_article(request, article_slug,
template_name='view_article.html',
form_class=CommentForm,
model_class=NewsArticle,
success_url=None,
):
urls.py:
(r'^news/(?P<article_slug>[-\w]+)/$', 'view_article', {}, "view_news_article"),
(r'^blog/(?P<article_slug>[-\w]+)/$', 'view_article', {'model_class': BlogArticle}, "view_blog_article"),
This makes your app highly reusable by offering the ability to override the template, form, model, and success_url straight from urls.py.

Categories

Resources