Django - Linking to web sections with buttons in a home page - django

Hi everyone and thanks for reading!
I'm a very novel user of Django. I decided to move from my basic web to django for learning how to use a framework web. I did the django tutorial but with my project... the way is not being hassle-free at all.
Let me first describe briefly my project so you can get an overview of the whole thing. My basic web consists of a home page and sections where you can change different parameters (such as room temperature) or check sensors data.
By now, I have the home page and the temperature control section running (with few things to fix, but correctly rendered). I would like to link every section with a button in the home page. This is my home page template:
{% extends 'base.html' %}
{% block content %}
<h1>Here goes a title</h1>
<p>A welcome message here...</p>
<h2>please select an action</h2>
<div id="column_left" class="column">
{% for action in actions_list_left %}
<div id="action_box1{{ forloop.counter }}" class="action_box">
<input type="button" onclick= " HELP HERE!! "
id= "{{ action.action_name }}_sel" class="action_button">
<div id="{{ action.action_name }}_desc" class="action_desc">
{{ action.description }}
</div>
</div>
{% endfor %}
</div>
<!--I ommit the right column, containing more actions...-->
{% endblock %}
I would like to use my "action" model fields to link to other sections. My idea is to use the action name field as the url of that section (to do it in a generic "model" way). For instance, if my home page is at localhost:8000/ and an action name is "temp", i would like the associated button to link to localhost:8000/temp and render the suitable template.
As I think is an urls.py issue, I post here my urls files (without import lines)...
urls.py
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', include('principal.urls')),
url(r'^temp/', include('temp.urls')),
)
principal/urls.py
urlpatterns = patterns('',
url(r'^$', 'principal.views.home', name='home'),
)
temp/urls.py
urlpatterns = patterns('',
url(r'^$', 'temp.views.index', name='temp_index'),
url(r'^(?P<pk>\d+)/$',
DetailView.as_view(
model=Room,
template_name='temp/roomTemp.html')),
)
I have tried a few ideas that I've read in other threads...
{% url temp:index %}
This one threw a NoReverseMatch error... 'temp' is not a registered namespace. Then I googled how to get through this and I changed this line in urls.py:
url(r'^temp/', include('temp.urls', namespace='temp')),
Also in temp/urls.py I changed the line:
url(r'^$', 'temp.views.index', name='temp'),
Both pages are still rendered OK, but the button is not working (does nothing)... It must be quite simple, but all the url thing seems a bit tricky to me (by the way the syntax sometimes is like a makefile mordor file :P). I'm using Django 1.3
Any help would be really appreciated. Also, any "good django coder" comment or explanation would be very useful, just to not make the same mistake again!
Thanks in advance,
Juan
EDIT:
I post the fix in the code here just in case someone find it useful:
<form action="{% url action.action_url %}">
<input type="submit" id="{{ action.action_name }}_sel" value="" class="action_button">
<div id="{{ action.action_name }}_desc" class="action_desc">
{{ action.description }}
</div>
</form>

If you don't need to use url namespaces you can do this
urls.py
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', include('principal.urls')),
url(r'^temp/', include('temp.urls')),
)
temp/urls.py
urlpatterns = patterns('',
url(r'^$', 'temp.views.index', name='temp_index'),
url(r'^(?P<pk>\d+)/$',
DetailView.as_view(
model=Room,
template_name='temp/roomTemp.html')),
)
And then in template
{% url 'temp_index' %}
Hope it works for you.

Related

Namespacing urls in django-registration

I want to keep a clean urls description in my projet, so I use namespaces:
project/urls.py:
urlpatterns = patterns('',
url(r'^contracts/', include('apps.contracts.urls', namespace='contracts')),
url(r'^accounts/', include('apps.registration_custom.backends.vince.urls', namespace='accounts')),
registration_custom/backends/vince/urls.py:
urlpatterns = patterns('',
url(r'^activate/complete/$',
TemplateView.as_view(template_name='registration/activation_complete.html'),
name='registration_activation_complete'),
# Activation keys get matched by \w+ instead of the more specific
# [a-fA-F0-9]{40} because a bad activation key should still get to the view;
# that way it can return a sensible "invalid key" message instead of a
# confusing 404.
url(r'^activate/(?P<activation_key>\w+)/$',
ActivationView.as_view(),
name='registration_activate'),
url(r'^register/$',
CustomRegistrationView.as_view(),
name='registration_register'),
url(r'^register/complete/$',
TemplateView.as_view(template_name='registration/registration_complete.html'),
name='registration_complete'),
url(r'^register/closed/$',
TemplateView.as_view(template_name='registration/registration_closed.html'),
name='registration_disallowed'),
(r'', include('registration.auth_urls')),
)
With this configuration, if I request /accounts/password/reset/ I get an error:
Reverse for 'django.contrib.auth.views.password_reset_done' with arguments '()' and keyword arguments '{}' not found
But if I'm not namespacing my urls, everything goes clean with my /accounts/password/reset/ request.
What I understand is that the django/contrib/auth/views/password_reset view is using reverse() on 'django.contrib.auth.views.password_reset_done'. And the urls dispatcher get lost because it should be asking for 'accounts:auth_password_reset_done'.
Am I guessing right?
Then what would be my options?
EDIT.
The template code that redirect to /accounts/password/reset :
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<form method="post" action="">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="{% trans 'Log in' %}" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
<p>{% trans "Forgot password" %}? {% trans "Reset it" %}!</p>
<p>{% trans "Not member" %}? {% trans "Register" %}!</p>
{% endblock %}
Wahaha, I've made a step in my Django's comprehension!
In fact, Django auth module is looking for a view when he asks for: reverse('django.contrib.auth.views.password_reset_done')
But my urls config is namespaces, so Django is lost (here I don't know exactly, maybe someone can explain better).
So I need to say to Django to look first for a non-namespaced url pattern first, just for it's core code.
So my trick is to add a line in the myproject/urls.py:
urlpatterns = patterns('',
url(r'^contracts/', include('apps.contracts.urls', namespace='contracts')),
# this is tricky
# the default auth module need to reverse some urls like reverse('django.contrib.auth.views.password_reset_done')
# but I want to keep a namespaced urls config
# then I need to supply a first url path to django when he look at non-namespaced urls
url(r'^accounts/', include('registration.auth_urls')),
url(r'^accounts/', include('apps.registration_custom.backends.vince.urls', namespace='accounts')),
And everything is working fine!
I admit that this is not an elegant solution, but it has the benefit to keep my namespaces right, so will be the templates.
Add correct namespace and app name for include('registration.auth_urls') (see last line)
urlpatterns = patterns('',
url(r'^activate/complete/$',
TemplateView.as_view(template_name='registration/activation_complete.html'),
name='registration_activation_complete'),
# Activation keys get matched by \w+ instead of the more specific
# [a-fA-F0-9]{40} because a bad activation key should still get to the view;
# that way it can return a sensible "invalid key" message instead of a
# confusing 404.
url(r'^activate/(?P<activation_key>\w+)/$',
ActivationView.as_view(),
name='registration_activate'),
url(r'^register/$',
CustomRegistrationView.as_view(),
name='registration_register'),
url(r'^register/complete/$',
TemplateView.as_view(template_name='registration/registration_complete.html'),
name='registration_complete'),
url(r'^register/closed/$',
TemplateView.as_view(template_name='registration/registration_closed.html'),
name='registration_disallowed'),
(r'', include('registration.auth_urls'), namespace='accounts', app_name='registration'),
)

Django: Next value is changing oddly in login page

I wanted to redirect the users in my app to their users page if they were already logged in and tried to go directly to "../login/". I've found this answer:
Django: Redirect logged in users from login page
It works fantastic until I decide to hit the "Registration" link I have below my login fields. I don't know why but when I hit it, I get redirect to the login page again but the only thing that changes is the url, for some reason it becomes "http://localhost:8000/users/login/?next=/users/register/", and it wont take me to my registration page.
Why the "next" variable changes if I've set it with another url in the login template like so:
{% extends "base.html" %}
{% block title %}User Login{% endblock %}
{% block head %}User Login{% endblock %}
{% block content %}
{% if form.errors %}
<p>User name or password is incorrect.</p>
{% endif %}
<form method="post" action="{% url login %}">
{% csrf_token %}
<p><label for="id_username">Username:</label>
{{ form.username }}</p>
<p><label for="id_password">Password:</label>
{{ form.password }}</p>
<input type="submit" value="Login" />
<input type="hidden" name="next" value="users/"/>
</form>
<li>Register</li>
{% endblock %}
I'm using django1.4 and python 2.7. My urls.py are:
For the whole application:
urlpatterns = patterns('',
url(r'^$', main_page, name="main_page"),
url(r'^users/',include('user_manager.urls')),
)
For the user_manager module:
urlpatterns = patterns('user_manager.views',
url(r'^$', users, name="user_page"),
url(r'^logout/$', user_logout, name="logout"),
url(r'^login/$', user_login, name="login"),
url(r'^(\w+)/$', user_page),
url(r'^register/$', register_page),
)
Do you have a #login_required decorator on that register_page view? If so, remove it
Ok I've found the problem. Django checks the urls regex in order so the "register" url was matching the "(\w+)/" intended to work for the users pages. So all I had to do is put that url at the end, the urls.py now looks like this:
urlpatterns = patterns('user_manager.views',
url(r'^$', users, name="user_page"),
url(r'^logout/$', user_logout, name="logout"),
url(r'^login/$', user_login, name="login"),
url(r'^register/$', register_page),
url(r'^(\w+)/$', user_page),
)
Nevertheless I still don't understand quite well why that mistaken match was changing the next value. I know that caused it but I don't know why...
Thank you very much for your time!

django registration urls

I am quite new to Django (have a background in python), and I am trying to build a simple webpage (normal stuff: registration, shopping cart, payments etc).
To this end, I am using the django-registration package and I have followed the instructions on: http://devdoodles.wordpress.com/2009/02/16/user-authentication-with-django-registration/
I have to say, I quite like it, and got it to work: and the registration pages look like admin panels. Now, I would like do some customization and I started off by including my own base.html. In the django-registration, I have some default templates, and the login temlates look like:
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<form method="post" action=".">
{{ form.as_p }}
<input type="submit" value="{% trans 'Log in' %}" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
<p>{% trans "Forgot password" %}? {% trans "Reset your account" %}!</p>
<p>{% trans "Not member" %}? {% trans "Register Now" %}!</p>
{% endblock %}
First, when I changed the I base.html to my own path, the page does not seem to render properly (although I see the text content, but the graphics are all missing), and I have noticed that all the links have gone a level down. For example, my Homepage ref has gone down to mysite.com/accounts/login/Homepage rather then my orginal mysite.com/Homepage.
As I unserstand, my url mappings do not seem right, but I cannot seem to find the url conf links. My current url conf looks like:
urlpatterns = patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
(r'^$', index),
(r'^Homepage$', index),
(r'^AboutUs$', AboutUs),
(r'^ContactUs$', ContactUs),
(r'^admin/(.*)', admin.site.root),
(r'^accounts/', include('registration.urls')),
(r'^$', direct_to_template,
{ 'template': 'index.html' }, 'index'),
Where do I find the registration url confs such as /accounts/login etc and the corresponding mapings?
Sorry if this is 101 django question!
Django registration supports pluggable backends, where the URLConf is provided by the backend module. You can take a look at the default backend urls on bitbucket.
The django-registration docs provide a pretty decent overview of how to set up your own templates. Basically, you want to create your own versions of each of the templates listed on that page. Django-registration does not provide any starter templates, but the docs are pretty clear about which context variables are available to each template.
Your URLConf looks OK, except that you don't want to have Django serving your media files. Assuming you're using Django 1.3, have a look at the staticfiles page in the docs. Basically, you use {{ STATIC_URL }} in your templates, get rid of the media/ URLConf entry, and things should Just Work on the development server.

django - set_language view giving me a "Page not found" error

Hi there
I've been following the docs on internationalization for django (using mezzanine on django 1.2.5) closely and everything is fine, except when i use a form like the one in the docs to switch language code
like this
<form action="/i18n/setlang/" method="post">
<input name="next" type="hidden" value="/whatever/" />
<select name="language">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}">{{ lang.1 }}</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>
with my urlconf looking like this
urlpatterns += patterns("",
("^admin/", include(admin.site.urls)),
("^", include("mezzanine.urls")),
(r'^i18n/', include('django.conf.urls.i18n')),
)
when i switch language and hit "go", i get a
Page Not Found (404)
Request Method: POST
Request URL: http://127.0.0.1:8000/i18n/setlang/
No Page matches the given query.
i added the i18n urls and the locale middleware alright.I tried it in a fresh project as well without luck.
Any clues?
Mezzanine's urlpatterns include a "catch all" for pages, so anything underneath it will never be found. To get your patterns working you simply need to swap the last two patterns in your urls.py to look like:
urlpatterns += patterns("",
("^admin/", include(admin.site.urls)),
(r'^i18n/', include('django.conf.urls.i18n')),
("^", include("mezzanine.urls")),
)

How can I get the reverse url for a Django Flatpages template

How can I get the reverse url for a Django Flatpages template
I prefer the following solution (require Django >= 1.0).
settings.py
INSTALLED_APPS+= ('django.contrib.flatpages',)
urls.py
urlpatterns+= patterns('django.contrib.flatpages.views',
url(r'^about-us/$', 'flatpage', {'url': '/about-us/'}, name='about'),
url(r'^license/$', 'flatpage', {'url': '/license/'}, name='license'),
)
In your templates
[...]
<span>{% trans "About us" %}</span>
<span>{% trans "Licensing" %}</span>
[...]
Or in your code
from django.core.urlresolvers import reverse
[...]
reverse('license')
[...]
That way you don't need to use django.contrib.flatpages.middleware.FlatpageFallbackMiddleware and the reverse works as usual without writing so much code as in the other solutions.
Cheers.
Include flatpages in your root urlconf:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
('^pages/', include('django.contrib.flatpages.urls')),
)
Then, in your view you can call reverse like so:
from django.core.urlresolvers import reverse
reverse('django.contrib.flatpages.views.flatpage', kwargs={'url': '/about-us/'})
# Gives: /pages/about-us/
In templates, use the {% url %} tag (which calls reverse internally):
<a href='{% url django.contrib.flatpages.views.flatpage url="/about-us/" %}'>About Us</a>
Write your base urls conf to point to your flatpages. Assume it is under pages:
urlpatterns = patterns('',
...
url(r'^pages/', include('project.pages.urls')),
...
)
Then write your flatpages as normal:
urlpatterns = patterns('django.views.generic.simple',
url(regex=r'^resume/$', view='direct_to_template', kwargs={'template': 'resume.html'}, name='resume'),
url(regex=r'^about/$', view='direct_to_template', kwargs={'template': 'about.html'}, name='about'),
url(regex=r'^books/$', view='direct_to_template', kwargs={'template': 'library.html'},name='books'),
)
Then your template just refers to them in the usual fashion:
<div id="pages">
...
<div class="pagelinks">
ABOUT
</div>
</div>
None of the solutions mentioned sufficiently followed the DRY principle in my opinion, so I just did this:
# core/templatetags/hacks.py
from django import template
register = template.Library()
#register.simple_tag
def flaturl(title):
"""
Returns the url for a flatpage based on the title.
NOTE: Obviously the title must be unique.
"""
from django.contrib.flatpages.models import FlatPage
try:
page = FlatPage.objects.get(title=title)
except:
return ""
return page.url
Then in any template that needs to make a link, I did this:
{% load hacks %}
...
Page Title
I might add some caching in there to keep the performance up, but this works for me.
I agree with Anentropic that there is no point in using Django Flatpages if you need to write urlconfs to employ them. It's much more straightforward to use generic views such as TemplateView directly:
from django.conf.urls import patterns, url
from django.views.generic import TemplateView
urlpatterns = patterns('',
url(r'^about/$', TemplateView.as_view(template_name="about.html"), name="about"),
)
Flatpages take advantage of FlatpageFallbackMiddleware, which catches 404 errors and tries to find content for requested url in your database. The major advantage is that you don't have to touch your templates directly each time you have to change something in them, the downside is the need to use a database :)
If you still choose to use Flatpages app, you'd better use get_flatpages template tag:
{% load flatpages %}
<ul>
{% for page in get_flatpages %}
<li>{{ page.title }}</li>
{% endfor %}
</ul>
Personally, I rarely reference flatpages outside of website's main menu, which is included via {% include 'includes/nav.html' %} and looks like this:
<ul>
<li>About</li>
<li>Credits</li>
...
</ul>
I don't feel I violate any DRY KISS or something:)
I thought the advantage of Flatpages was you didn't have to create any view stubs or url confs? It's a bit pointless otherwise... if you're creating views and urls you may as well save the flatpage content as template html instead.
try this instead:
https://github.com/0sn/nameremoved/wiki/flatpages
When you create any flatpage, you need to specify an URL which is saved as part of the model. Hence you can retrieve the URL from any flatpage object. In a template:
{{ flatpage.url }}
Remapping flatpage URLs in urls.py and then having to use reverse sort of defeats the purpose of the flatpages app.
You need to redeclare the url conf and cannot rely on the official 'django.contrib.flatpages.urls' that the doc is encouraging us to use.
This won't be more difficult, just include in your urls.py
from django.conf.urls import patterns, url
urlpatterns += patterns('',
...
url(r'^pages(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage', name='flatpage'),
...
)
And now you can use your usual reverse url template tag
<a href='{% url 'flatpage' url="/about-us/" %}'>About Us</a>
Or to display a list of all flat pages
<ul>
{% get_flatpages as flatpages %}
{% for page in flatpages %}
<li>{{ page.title }}</li>
{% endfor %}
</ul>
proper Django>= 1.10:
urls.py
urlpatterns += [
url(r'^(?P<url>.*/)$', flatpage, name='flatpage'),
]
easy lookup inside the template:
{% url "flatpage" url="SOME_URL" %}
where SOME_URL is the value frome the flatpage.url field
According to this django documentation for flatpages
You can simply do
{% load flatpages %}
{% get_flatpages as flatpages %}
<ul>
{% for page in flatpages %}
<li>{{ page.title }}</li>
{% endfor %}
</ul>
In your template.