Resolving reverse urls in django - 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)])

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.

Django: how to simplify calls for rendering templates from subdirectory

I have django project with a couple applications. To be able use templates with common names (like index, menu, ..., page1, page2) in more then one of them I adopted this schema:
app1/
templates/
app1/
page1.html
page2.html
app2/
templates/
app2/
page1.html
page2.html
and in views I use it like that:
def myview(request): # in app1
context={'name':'John', 'surname':'Lennon'}
return render(request,"app1/page1.html",context)
or
def myview(request): # in app2
context={'tool':'hammer', 'size':'big'}
return render(request,"app2/page1.html",context)
it works, but I have to write the full app name (app1/, app2/) in each and every render (and no app uses templates from other app or just from templates/ (except the project itself) ) and the apps names are actually long like 10-17 characters (not short as app1, app2)
The question: is there a way to do it better, that each applications render would not default to templates/ but to templates/app1/, templates/app2/ and so, respectively?
Thanks for all suggestions
One simple solution is, you can declare the path on top of the app or in settings.py and use that variable in entire script, for example:
path1 = "app1/templates/"
path2 = "app2/templates/"
def myview(request): # in app1
context={'name':'John', 'surname':'Lennon'}
return render(request,path1+"page1.html",context)
def myview(request): # in app2
context={'tool':'hammer', 'size':'big'}
return render(request,path2+"page1.html",context)
This can also reduce the typing efforts.

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.

ImportError After Moving App to Nested Folder

My application was working fine when I wanted to see whether I could organize my project in a better way. I read through this tutorial on structuring a django project.
Before my project structure was as follows:
camucamu
books
admin.py
models.py
views.py
__init__.py
static
templates
urls.py
views.py
settings.py
wsgi.py
__init__.py
What I wanted to do was move the books app into an apps folder. Thus I did that and changed the project structure to the following:
camucamu
apps
books
admin.py
models.py
views.py
__init__.py
static
templates
urls.py
views.py
settings.py
wsgi.py
__init__.py
I then changed the imports in views.py and admin.py
from books.models to apps.books.models.
I also changed INSTALLED_APPS in settings.py from books to apps.books.
When I then tried to run syncdb, I get the following error:
raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
django.core.exceptions.ImproperlyConfigured: ImportError apps.books: No module named apps.books
What am I messing up here so it can't find my app anymore?
Your apps folder does not have an __init__.py file so it cannot be recognized as a python module
I got the same error, following the same guide, as the last point of the following list was not cited. Make sure you performed the following changes:
Create a blank __init__.py file inside the apps folder (needed for python to recognize it as a package)
Update the import statements wherever you refer to an external app:
from projectname.apps.appname.models import YourModel, YourOtherModel
Inside settings.py edit INSTALLED_APPS such that it looks like this:
INSTALLED_APPS = (
...
# apps
'projectname.apps.appname1',
'projectname.apps.appname2',
)
This one is not specified in the guide: In all your urls.py files, update the urlpatterns!
BEFORE:
# client views
urlpatterns += patterns('appname',
...
)
AFTER:
# client views
urlpatterns += patterns('projectname.apps.appname',
...
)
Finally remember to update your changes by calling python manage.py syncdb
Hope that helped.

Custom admin interface in Django

Django's documentation provides an easy way of installing admin app.
It assumes the structure of files as follows:
mysite/
manage.py
mysite/
settings.py #adding `admin` under `INSTALLED_APPS`
__init__.py
urls.py #adding urls
wsgi.py
myapp/
__init__.py
admin.py #creating this file
models.py
views.py
My question is how to get the admin interface to work if my structure is as follows:
mysite/
manage.py
settings.py
__init__.py
urls.py
myapp/
__init__.py
forms.py
models.py
views.py
What will be the various changes that I will have to incorporate to get the admin interface working. [my other apps are working].
I have read and read the documentation several times.
I'm using Django 1.4.
EDIT#1
I'm getting this error on running localhost:8000/admin/:
error at /admin/
unknown specifier: ?P[
Whole error here.
My urls.py file has the lines [as in the docs]:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/(.*)', include(admin.site.urls)),
)
My admin.py file in the myapp folder has the code:
import models
from django.contrib import admin
class PostAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
admin.site.register(models.Article, PostAdmin)
This is how you're supposed to include the admin urls:
url(r'^admin/', include(admin.site.urls)),
The documentation shows this.
The error that you're getting is coming straight from the re python module, complaining about this part of a url:
?P[
The URLs you've posted in your comment beneath show this:
url(r'^(?P[-a-zA-Z0-9]+)/?$', 'myapp.views.getPost')
Try changing that url by giving the match group a name:
url(r'^(?P<slug>[-a-zA-Z0-9]+)/?$', 'myapp.views.getPost')
And in your getPost view, include a slug argument.