Does my templates directory need a __init__.py file? - django

I'm using Django and Python 3.7. I have the following in my project hierarchy ...
+ project
+ web
+ views
tax_calculator.py
+ forms
__init__.py
tax_calculator_form.py
+ templates
tax_calculator.html
My view file, "tax_calculator.py" is attempting to render a GET request, using
# Basic function that serves the default page
def get(request):
tax_calculator_form = TaxCalculatorForm()
return render(request, "web/templates/tax_calculator.html", {'form': tax_calculator_form})
but I'm getting the error
TemplateDoesNotExist at /calculate_taxes
when I visit my URL and it's complaining about this line in my view
return render(request, "web/templates/tax_calculator.html", {'form': tax_calculator_form})
The path looks correct to me. Why isn't my URL finding my template path?

In answer to your questions title, No. __init__.py is for python modules, not asset directories
Depending on how you've specified your template settings, you shouldn't need the relative path, "tax_calculator.html" should suffice.

Related

pass data from Django view to react

I have a django view that returns a variable in order to be rendered in template
return render_to_response('index.html', {
'courses': courses})
I'm using ReactJS to render the index.html file, but I'm not sure whether i have to point to index.html in my view or the ReactJS file.
If I have to point to index.html how can I use the courses variable with React ?
Update
the variable courses that i'm passing is of type dictionnary
Templates processing is anterior to any sort of JavaScript interpretation. This means that you will have to, in some sense, emulate its hardcoding beetween the js tags.
First, know that the python dictionary is likely to be corrupted when received on the client side. To prevent this, you may want to send it as a json object. Which means that, in you script views.py, you will have to json.dumps your dictionary. As follows
from django.shortcuts import render
import json
#...
#...
return render(request,
'your_app/index.html',\
{'courses': json.dumps(courses)}\
)
Note that I use render instead of render_to_response, because render is a brand spanking new shortcut for render_to_response in 1.3 that will automatically use RequestContext
Also, note that you do have to point to your index.html, but the exact path depends on the strucutre of your project. Above, I assume you followed the recommended django project layout, i.e.
myproject/
manage.py
your_project/
__init__.py
urls.py
wsgi.py
settings/
__init__.py
base.py
dev.py
prod.py
your_app/
__init__.py
models.py
managers.py
views.py
urls.py
templates/
your_app/
index.html
[...]
Then, on the html side,
...
<script>
var courses = {{courses|safe}}
// working with the variable courses
</script>
...
Now, you can do what you want with it, be it with ReactJS library.

Resolving reverse urls in django

Consider the following django site structure:
root/
- manage.py
- main/
-- __init__.py
-- settings.py
-- urls.py
- phase1/
-- __init__.py
-- urls.py
-- phase1/content/
--- __init__.py
--- models.py
--- views.py
i.e. 3 apps, main/, phase1/ and phase1/content/.
The root_url of the settings is main/url.py and
the relevant code of the modules are:
#main/urls.py
urlpatterns = patterns('',
url(r'^phase1/', include('phase1.urls')),)
#phase1/urls.py
url(r'^problem/(\d+)/$', content.views.view_problem, name='problem')
#phase1/content/models.py
class Problem(django.db.models.Model):
## stuff and fields
def get_absolute_url(self):
return django.core.urlresolvers.reverse('content.views.view_problem',
args=[str(self.id)])
it is clear that a request of url /phase1/problem/1/ asks for content.view.view_problem with the correct argument. However, the reverse function is not generating this path when it is used (on a template for instance).
If I add the prefix 'phase1.' on the first argument of reverse():
return django.core.urlresolvers.reverse('phase1.content.views.view_problem',
args=[str(self.id)])
it works. This is not what I want because phase1/ and content/ are supposed to be portable apps in the django sense, so "phase1" should not be inside the code of content/ app...
Maybe I'm missing something. Can someone give a proper explanation on why this is happening and a solution?
You need to use the name of the url in the reverse.
ie,
return django.core.urlresolvers.reverse('problem',
args=[str(self.id)])

Django on APP Engine - error redirecting a URL path to an existing function in views.py (on urls.py)

I'm getting an error when I try to redirect a URL path to an existing function inside of a views.py file.
I realize where the problem is, but I cannot figure out how to solve it.
I have the following structure of folders on my project:
my_app_gae
app.yaml
main.py
settings.py
urls.py
my_app_django (<-- here is my django project)
dashboard
views.py
models
models.py
The problem comes here:
when I edit the urls.py file, when I try to redirect a specific URL path to an existing function inside of views.py (landing), I recieve the following error:
Request Method: GET
Request URL: http://localhost:8090/landing/
Exception Type: ImportError
Exception Value: No module named my_app_django
The value of my Python Path is: V:\Python~1\my_app_gae (the place where the structure of folders I wrote before is).
The url.py value that I'm trying to execute is:
from django.conf.urls.defaults import *
from my_app_django.dashboard.views import landing
urlpatterns = patterns(
'',
(r'^landing/$', landing),
)
If I copy the views.py file directly on the my_app_gae directory it works. The problem comes when the views.py file is inside of other directories.
Thanks a lot.
Regards
To be recognized as a Python package, you need empty files named __init__.py in each subdirectory.

Dajaxice network error 404: method not found

I'm trying to create a basic submit form (like the dajaxice's example) but i keep receiving a 404 error from firebug console:
404 NOT FOUND 386ms
"NetworkError: 404 NOT FOUND - http://<my_website>/dajaxice/maynard.maynard_core.subscribe/"
My project folder structure is
/maynard/maynard_core/
This folder contains the main files of the project (views.py, ajax.py etc etc... main django project folder)
Inside the ajax.py file, there's the subscribe method:
from dajax.core import Dajax
from dajaxice.core import dajaxice_functions
from dajaxice.decorators import dajaxice_register
from views import subscribe_search
from forms import SubscriptionForm, SendMailForm
from django.core.mail import send_mail
def subscribe(request, form):
if request.POST:
dajax = Dajax()
form = SubscriptionForm(form)
try:
if form.is_valid():
url = form.cleaned_data['url_sub']
what = form.cleaned_data['what_sub']
where = form.cleaned_data['where_sub']
mail = form.cleaned_data['email']
subscribe_search(url,what,where,mail)
dajax.assign('#sub_mess_top','innerHTML','Thank you for subscribing to the search')
else:
dajax.add_css_class('#sub_mess_top','text error-message')
dajax.assign('#sub_mess_top','innerHTML','Couldn\'t complete the request, try again!')
return dajax.json()
except:
dajax.add_css_class('#sub_mess_top','text warning-message')
dajax.assign('#sub_mess_top','innerHTML','You already saved this search')
return dajax.json()
dajaxice_functions.register(subscribe)
Which is then called via this js method
function send_form_top(){
data = $('#subscribe').serializeObject(true);
Dajaxice.maynard.maynard_core.subscribe(Dajax.process,{'form':data});
}
The form is a basic form with action "#" and onclick="send_form_top();"
I followed the installation and configuration guide (settings configured, urls configured etc etc etc), and it's a very 101 implementation.
in urls.py
from dajaxice.core import dajaxice_autodiscover
dajaxice_autodiscover()
...
django.conf.urls.defaults.url(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, django.conf.urls.defaults.include('dajaxice.urls')),
I added 'dajaxice' to my installed apps in settings.py, and DAJAXICE_MEDIA_PREFIX is 'dajaxice' (as in the docs).
Templates are fine too (since i have the dajaxice dynamically compiled js included)
But still i can't seem to be able to make it work. I checked throu the response headers, and this is what i get for the dajax.js file:
maynard_core: {
subscribe: function(callback_function, argv, custom_settings){
Dajaxice.call('maynard.maynard_core.subscribe', callback_function, argv, custom_settings);
},
...
This tells me that the submit method, which is in the ajax.py file inside maynard/maynard_core/ is actually included and the callback is correct too. I really don't know how to debug this any more, django logs shows nothing about it. Thanks all in advance, i'm really loosing my hair on this.
If you got a 404 error, definitely the problem is in your urls.py configuration.
There is any wildcard url above the dajaxice one? Try to put the dajaxice url conf on the beginning and see what happens.
Anyway... are your views.py, ajax.py, etc... inside any app? or all of them are in the root project folder. That could be the problem too.

Django view - load template from calling app's dir first

I try to keep a somewhat consistent naming scheme on my HTML templates. I.e. index.html for main, delete.html for delete page and so forth. But the app_directories loader always seems to load the template from the app that's first alphabetically.
Is there any way to always check for a match in the calling app's templates directory first?
Relevant settings in my settings.py:
PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))
TEMPLATE_LOADERS = (
'django.template.loaders.app_directories.load_template_source',
'django.template.loaders.filesystem.load_template_source',
)
TEMPLATE_DIRS = (
os.path.join(PROJECT_PATH, 'templates'),
)
I've tried changing the order of TEMPLATE_LOADERS, without success.
Edit as requested by Ashok:
Dir structure of each app:
templates/
index.html
add.html
delete.html
create.html
models.py
test.py
admin.py
views.py
In each app's views.py:
def index(request):
# code...
return render_to_response('index.html', locals())
def add(request):
# code...
return render_to_response('add.html', locals())
def delete(request):
# code...
return render_to_response('delete.html', locals())
def update(request):
# code...
return render_to_response('update.html', locals())
The reason for this is that the app_directories loader is essentially the same as adding each app's template folder to the TEMPLATE_DIRS setting, e.g. like
TEMPLATE_DIRS = (
os.path.join(PROJECT_PATH, 'app1', 'templates'),
os.path.join(PROJECT_PATH, 'app2', 'template'),
...
os.path.join(PROJECT_PATH, 'templates'),
)
The problem with this is that as you mentioned, the index.html will always be found in app1/templates/index.html instead of any other app. There is no easy solution to magically fix this behavior without modifying the app_directories loader and using introspection or passing along app information, which gets a bit complicated. An easier solution:
Keep your settings.py as-is
Add a subdirectory in each app's templates folder with the name of the app
Use the templates in views like 'app1/index.html' or 'app2/index.html'
For a more concrete example:
project
app1
templates
app1
index.html
add.html
...
models.py
views.py
...
app2
...
Then in the views:
def index(request):
return render_to_response('app1/index.html', locals())
You could even write a wrapper to automate prepending the app name to all your views, and even that could be extended to use introspection, e.g.:
def render(template, data=None):
return render_to_response(__name__.split(".")[-2] + '/' + template, data)
def index(request):
return render('index.html', locals())
The _____name_____.split(".")[-2] assumes the file is within a package, so it will turn e.g. 'app1.views' into 'app1' to prepend to the template name. This also assumes a user will never rename your app without also renaming the folder in the templates directory, which may not be a safe assumption to make and in that case just hard-code the name of the folder in the templates directory.
I know this is an old thread, but I made something reusable, that allows for simpler namespacing. You could load the following as a Template Loader. It will find appname/index.html in appname/templates/index.html.
Gist available here: https://gist.github.com/871567
"""
Wrapper for loading templates from "templates" directories in INSTALLED_APPS
packages, prefixed by the appname for namespacing.
This loader finds `appname/templates/index.html` when looking for something
of the form `appname/index.html`.
"""
from django.template import TemplateDoesNotExist
from django.template.loaders.app_directories import app_template_dirs, Loader as BaseAppLoader
class Loader(BaseAppLoader):
'''
Modified AppDirecotry Template Loader that allows namespacing templates
with the name of their app, without requiring an extra subdirectory
in the form of `appname/templates/appname`.
'''
def load_template_source(self, template_name, template_dirs=None):
try:
app_name, template_path = template_name.split('/', 1)
except ValueError:
raise TemplateDoesNotExist(template_name)
if not template_dirs:
template_dirs = (d for d in app_template_dirs if
d.endswith('/%s/templates' % app_name))
return iter(super(Loader, self).load_template_source(template_path,
template_dirs))
The app_loader looks for templates within your applications in order that they are specified in your INSTALLED_APPS. (http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types).
My suggestion is to preface the name of your template file with the app name to avoid these naming conflicts.
For example, the template dir for app1 would look like:
templates/
app1_index.html
app1_delete.html
app1_add.html
app1_create.html