Creating Generic Views in Django - python

Ok so I am new to Django but not to the MVC world (built a few apps in Grails)...but I seem to be having the same issue as a bunch of people and I am hoping someone can shed some real light on Django's Class based generic views. In the Grails world "templates" or generic views CAN BE generated by the framework and I believe the same thing is true regarding Django but if you follow the 1.7 "Writing your first django app" there seems to be some special magic missing.
I have the following project/app structure:
mysite
->mysite
->settings.py
->urls.py
->_init_.py
->wsgi.py
->polls (my app)
->models.py
->urls.py
->views.py
->templates
->polls
In the tutorial we are asked to created an index.html, details.html, results.html file in the templates->polls directory and we have some simply HTML views within those files. That all works great. Once I get to "Use generic views: Less code is better" in the tutorial is where I get into trouble. Am I wrong in assuming I should simply REMOVE the index.html, details.html, results.html files from the templates folder AND that Django should be generating views on the fly? I assumed that was the point of the generic views but now I am not sure. When I do remove the views I get a templatedoesnotexist error. Do I need to do something to my settings.py to let it know that I want to look to django to generate the views? The following is the standard generated settings (which is what I have) and I assume that should be sufficient to perform default behaviors?
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
TEMPLATE_DEBUG = True
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates/'),]
If you need more from me let me know, but basically I am wondering if I am way off on assuming Django generates the views from a template or not? Thank you!

You're just a bit confused about Django's terminology. Almost all views use a template to render the actual markup (HTML, XML, whatever) that is sent back to the browser.
A Django Generic View is just a Class based version of writing your own functional view. So instead of something like:
def show_template_with_data(request):
template = "myapp/show_data.html"
return render(request, template, {'data1': 1, 'data2': 2})
you would use Python classes and OO and do:
class ShowTemplateWithData(TemplateView):
template_name = "myapp/show_data.html"
def get_context_data(self, **kwargs):
context = super(ShowTemplateWithData, self).get_context_data(**kwargs)
context['data1'] = 1
context['data2'] = 2
return context
These two are equivalent one is just using functions and the other Class Based Views.
In Django, views are the code that determines what action is taken, what data is given to the template (for example based on logged in user), etc. a "template" is just the HTML with placeholders/loops/etc that displays it.
But no, you shouldn't be deleting the template HTML files, both styles of views will need them.

Related

Overriding a template in Django

I'm using this library to add a sessions tab on my django project. I'm calling the module's template from my project using this line:
<li>Sessions</li>
It works, but now I'd like to style the page, and to do that I need to override the module's template with my own template. So, as the module says here, I inherited the module's SessionListView on my own views.py to overrode the template:
from user_sessions.views import SessionListView
class MySessionList(SessionListView):
template_name = 'user_sessions/session_list.html'
Then I added the url to my urls.py
url(
regex=r'^account/sessions/$',
view=MySessionList.as_view(),
name='sessions',
),
And then I created my template on my own project which is located like this:
templates/user_sessions/session_list.
But for some reason, I still can't see MY template appearing, the module's template keeps appearing instead. Can anyone help me finding what I'm doing wrong?
The SessionListView already uses user_sessions/session_list.html by default, so your custom view isn't required.
It sounds like Django is finding the user_sessions/session_list.html template in the user_sessions app before your template. If your template is in an app's templates directory, then you can fix this by moving your app above user_sessions in your INSTALLED_APPS setting.
Alternatively, if you move your template to a directory in the 'DIRS' list in the TEMPLATES setting, then Django will find your template before it checks the app templates directories. This is cleaner if your overridden template doesn't really belong to any of your apps, and another advantage is that you don't have to re-order the INSTALLED_APPS list.
See the docs on overriding templates for more information.

Django widget template override does not search in the project template directory. How to fix?

I am attempting to override a built in widget template in Django 1.11. I seem to be doing everything that the docs say to do in this regard, but for the widget templates, Django is not looking in my project at all, and I get a TemplateDoesNotExist error.
Here's what I have for the override:
class MyFileWidget(widgets.FileInput):
template_name = 'myapp/my_file_widget.html'
The template is definitely there. If I pass the template to a render call, it finds it fine. Problem is an issue of paths. When calling render from a view, it checks the following:
projectroot/templates/myapp/my_file_widget.html
djangoroot/forms/templates/myapp/my_file_widget.html
When it finds the template in my project, it renders it. This is NOT happening when I provide the template path in the class above. In that case, it does not check in my project templates, where the file actually exists, and begins checking in the django path, where it does not. Hence the error message.
So I have no clue why this the loader would check my project templates on render calls, but then fail to do so when looking for the "template_name" of the widget override. Any ideas?
By default, the FORM_RENDERER setting defaults to 'django.forms.renderers.DjangoTemplates'.
This checks your apps' templates directory (e.g. projectroot/myapp/templates/myapp/my_file_widget.html), but it does not check your project's template directories (e.g. projectroot/templates/myapp/my_file_widget.html).
If you want to use the same configuration as your TEMPLATES setting, then you should use the TemplatesSetting renderer.
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
You will also need to update your TEMPLATES setting so that Django can still use the built in widget templates. The easiest way to do this is to add django.forms to INSTALLED_APPS. See the docs for more info about this.

Subclassing and overriding Django Class based views

I'm building a website using django-all auth for it's authentication and social authentication functions. The forms that come bundled with the app are hardly great to look at and hence I decided to create my own views.
The problem is: How do I create them while ensuring that the backend of Django all auth is still available to me? I've dug into the source code and found that it uses class based views for rendering and performing CRUD operations.
I want to know if I can subclass those views in my own app/views.py and just change their template_name field to my own templates. Any advice would be most helpful.
Thanks.
You can of course subclass the views, as long as you change your URLs to point to the overridden versions. However, there is no need to do this just to use your own templates; Django's template loader is specifically written with this use case in mind. Simply create your own directory inside your templates folder to match the one allauth is using, and create your own template files inside it; Django will find yours first and use them.

Django project structure,

I'm new to Django and trying to understand the "correct" way to structure my project, in particular when and how to put separate functionality within an application.
The site I am building will include mainly static information (it's for a holiday cottage) which I'm providing with views from the main site project. I also want to include a calender, which will display availability in a sidebar, which I have started to build as an application "availabilityCalender" as it will be reused across most pages and I can see me using it in other projects.
What I can't figure out is how to hook this into a page view from my application. Most tutorials online approach applications as representing the entire page and link into a view from the urls.py of the project. Instead I'm want to add the application as a part of my page. The simplest way to represent what I'm trying to do is below:
from django.shortcuts import render
from django.http import HttpResponse
import availabilityCalender
def index(request):
availabilityCalender.views.monthView()
I was hoping that this would simply add the application's view into the index view. When testing this I get the error "errorAttributeError at /, 'module' object has no attribute 'views'".
Am I trying to use applications is a way the are not designed for or simply using the wrong approach? My apologies for what is almost certainly an incredibly simple question!
Edit -
I got the above code to work by changing my import:
from availabilityCalender.views import monthView
def index(request):
return monthView(request)
One way to do this would be to use template inheritance. Each one of your templates could extended a base template that includes your calendar.
Another way would be to put your calendar in its own template and to use the {% include %} template tag.
If your calendar has data associated with it, the next issue would be getting that data to the templates. If you are including the calendar on every page of your site you could create a custom context processor that automatically adds the calendar data to every request.
If the calendar is only on some pages you could just load the data on a view by view basis. Perhaps you could extract the calendar functionality into a CalendarMixin view that loads the correct calendar data in get_context_data.
first of all your project should have a structure similar to this:
-/myProject
-/myproject
-settinngs.py
-views.py
-urls.py
-/templates
-mange.py
-/availabilityCalender
-models.py
-views.py
Now you need to make sure you add to your settings INSTALLED_APPS the app "myproject.availabilityCalender", Once this is done its quite simple to use and reuse your app in all project and further apps. In this specific case if you want to import and use your app on the myproject/views.py, just do:
from myproject.availabilityCalender.models import <--MODULES YOU NEED FOR YOUR VIEW-->
def monthView(request):
.
.
.
return render(request, 'index.html')

Include Django Project specific objects in Django package

I'm developing a web-app with common components and decided to pack those common components (some views, templates, logic) in a Django package.
Now the problem is: I want to access variables of my specific Django project, depending on the project, from the package. In this specific instance:
My Django package has an admin panel. A custom-made admin panel that allows me to manage a list of algorithms. However, these algorithms change. In one specific Django project I might have 3 algorithms, in another one I might have 5.
The admin panel in the Django package allows me to edit custom algorithm components, such as weights, test cases, etc.
Now my problem is, in the Django view, in the package, I want to access the Django project's algorithms in order to show them. As a list, for selection/editing/deleting, but also to view them in detail and edit them.
Now my problem is, obviously, I can't include something from the Django project in the Django package, otherwise it would become a dependency. And the algorithms are different and unique in each specific project.
So, in short, the question is how to access specific data of a Django project by a package used by that project, without making the package dependent of anything.
OK, so after some more investigation I found a possible solution for this. Will leave it here for informational purposes while waiting for an answer.
Instead of loading the package URLs as a module I use a custom function that passes the Django project's variables to the package URLs, and therefore, the views.
So in the project urls.py, instead of:
url(r'^package/$', include('package.urls'))
I use
url(r'^package/$', obtain_package_urls(custom_content))
where obtain_package_urls() is a function in the package:
def obtain_package_urls(custom_content):
urlpatterns = patterns('',
url(r'^url1$', view1, {'custom_content': custom_content},
url(r'^url2$', view2, {'custom_content': custom_content},
)
return (urlpatterns, None, None)
The goal is to, instead of the include function that includes the static URL-view mapping of Django, to use this function that returns a dynamic URL-view mapping with the custom content included in the views.
So in effective terms with the algorithms I ended up doing:
#Django project settings.py
obtain_algorithm_list():
return Algorithm.objects.all()
#Django project urls.py
from project.settings import obtain_algorithm_list
urlpatterns = ...
...
url(r'^package/$', obtain_package_urls(obtain_algorithm_list())
...
#In the package urls.py
urlpatterns = ...
url(r'^view1/$', view1, {'algorithms': algorithms},
...
#And then in each package view
def view(request, algorithms=[]):
...
use_for_something(algorithms)

Categories