Unable to change Django default templates - python

I'm learning Django using W. Vincent's "Django for beginners". I got to the part where we have to customize the password change page (p. 186). According to the author:
"Django already has created the views and URLs for us, we only need to
change the templates."
I created a new template password_change_form.html but when I start a local server and go to the localhost/accounts/password_change, I still see the old default page with the "Django Administration" header. Here is the code:
{% extends "base.html" %}
{% block title %}Password Change{% endblock title %}
{% block content %}
<h1>Password change</h1>
<p>Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly.</p>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input class="btn btn-success" type="submit" value="Change my password">
</form>
{% endblock content %}
I'm surprised because everything worked well up until this point, as I was able to successfully updated the login and signup pages' templates. What do you think might be going wrong? Thanks.

This is happening because in "Django For Beginners" book, the author does not configure static file setting in the settings.py file the css you are seeing in the template is because of bootstrap's cdn.
If you want to clear that problem you have to configure static files settings in settings.py.
This article by the same author can be helpful for you

Related

Implementing Django Bootstrap crispy forms into default signup / login pages?

I've set up user account signup and login pages following this tutorial and it all works great, except the pages have no formatting. I'm now looking for a simple drop in solution to improve the appearance of "templates/registration/login.html" and "templates/registration/signup.html". Someone recommended crispy forms which look great, and as the rest of my site uses Bootstrap 5, crispy-bootstrap5 looks ideal.
I'm struggling to implement crispy-bootstrap5 as I don't understand Django's inbuilt django.contrib.auth.forms nor forms in general, and can't find simple reproducible examples for crispy forms with signup.html and login.html. I've installed packages fine, but now don't know how to beautify login.html and signup.html from that tutorial:
{% extends 'base.html' %}
{% block title %}Sign Up{% endblock %}
{% block content %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign Up</button>
</form>
{% endblock %}
I don't know where to go with this, but the docs for regular django-crispy links to a gist for an eg form, and the index.html {% load crispy_forms_tags %} and {% crispy form %}. I've put them in which mostly left the page unchanged except for messing up the formatting. I think I now need to modify class CustomUserCreationForm(UserCreationForm) in forms.py but I don't know how. I'm also reluctant to risk bigger problems by modifying Django's inbuilt functionalities I don't understand.
What steps need we take to get login.html and signup.html looking like bootstrap 5?
please follow bellow steps to use crispy_forms with bootstrap5:
1st step: Install crispy_forms form bootstrap 5
pip install crispy-bootstrap5
step 2: Add crispy_forms and crispy_bootstrap5 to installed apps
INSTALLED_APPS = (
...
"crispy_forms",
"crispy_bootstrap5",
...
)
step 3: add crispy form attr to settings file
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"
check here for details
to use crispy form in templates, add {% load crispy_forms_filters %} and {% load crispy_forms_tags %} on top of your sign up and login page.
and declare form as crispy i.e {{forms| crispy}} or field as {{ form.fieldname|as_crispy_field }}

Major issue: Dropdown switcher in Mezzanine uses default settings of main site when logged in

In Mezzanine there's a dropdown list of available sites on the multi tenancy project that I created.
The problem is when a user is logging in to their blog e.g. blog.domain.com the user gets the default choice of domain.com and so their posts etc won't show up for some reason. It's not even public when I am logged out also...
The source of this switcher:
{% if dropdown_menu_sites and dropdown_menu_sites|length > 1 %}
<form action="{% url "set_site" %}">
<input type="hidden" name="next" value="{{ request.path }}">
<select name="site_id" onchange="this.form.submit();">
{% for site in dropdown_menu_sites %}
<option value="{{ site.id }}"
{% if site.id == dropdown_menu_selected_site_id %} selected{% endif %}
>{{ site }}</option>
{% endfor %}
</select>
</form>
{% endif %}
I can't really figure out what's causing this and how to modify it so that the blogger can login and expect to have control over their settings for the blog.
That's not how it works. According to Stephen McDonald (the creator) he says (quote):
Some things to note:
Site selector in admin won't change the URL being used to access the
admin over, it sets a session variable controlling which site data is
being used - this is so that the admin can always be access over a
single domain which may be the only one containing an SSL
certificate.
If you view the front-end site as a logged-in administrator with the
session variable set, that site's data will be used regardless of the
host being accessed - this is so that the content administrator can
preview their changes, regardless of which host their authenticated
session is tied to.
Link: https://github.com/stephenmcd/mezzanine/issues/1467#issuecomment-165626948

Django Development Server, blank HttpResponse on Post Method

I am developing an application in Django using Heroku's tools and guides for doing so, and have ran into an issue. On my local dev environment I cannot get a response from my views if it I use the post method. Currently i'm using a simple form to post a collection of ids to a view.
def webinarToHS(request):
errors = []
if request.method == 'GET':
webinars = get_upcoming_webinars()
return render_to_response('webinarToHS.html', {'webinars': webinars.json(), 'length': len(webinars.json())/2}, RequestContext(request))
elif request.method == 'POST':
method = request.method
return HttpResponse("test")
In the console it comes back with a 200 response ok. However the browser displays a blank html page (empty body tags).
On the production/heroku server, i get back a response, so I don't believe there is an issue with the code itself but rather with my settings file. I went back through the heroku django setup guide and used an environment variable on my local machine to switch those settings off if i'm in local dev but I am still having this issue.
Can anyone give me a clue as to where to start looking for a fix? I'm running windows 7 with a virtualenv wrapper, python 2.7.5 and django 1.5
Thanks.
As per requested in the comments, the WebinarToHS template file is as below:
<html>
<head>
<title>Add Webinars to Hubspot</title>
<style>
html, body {background-color: #eee;}
#wrapper {background-color: #fefefe; width:60%; margin:0 auto; position:relative; margin-top:50px; padding:25px;}
form {text-align:center;}
label {font-weight:bold;}
.submit {float:right;}
.check {float:left; text-align:left; max-width:48%; margin-right:2%;}
</style>
</head>
<body>
<div id="wrapper">
<form name="form" action="{%url 'G2WApi.views.webinarToHS' %}" method="post">
{% csrf_token %}
<label for="webinarKey">Choose the Webinar(s) you would like to add to hubspot:</label><br/><br/>
<div class="check">
{% for webinar in webinars %}
<input type="checkbox" name="webinars[]" value="{{ webinar.webinarKey }}" />{{ webinar.subject }}<br/>
{% if forloop.counter|divisibleby:length %}
</div><div class="check">
{% endif %}
{% endfor %}
</div>
<div style="clear:both; height:10px;"></div>
<input class="submit" type="submit" value="Add to Hubspot" />
</form>
</div>
</body>
</html>
Although it doesn't actually solve the question at hand, I found a way that was much better for what I was trying to do. I discovered that everything in my code for the POST Method worked except the output or rendering of a template. HttpRedirection worked, and also the Django Messages System. I found a tutorial on how to use that and it works perfectly for posting responses back to the originating template.
The Django Messaging system, for those who aren't aware, is a way to add details back to the originating request object. Here's a snipper
messages.success(request, "success message")
return HttpResponseRedirect(request.path)
The first line of code is attaching the message to the request object (in this case the same one that was passed in to the view) and then in the second line of code we are just redirecting back to the requesting path. Django handles all the rest you just have to add some code to your template like follows:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
to loop through and display your messages however you wish. I hope this helps someone.

How to use the built-in 'password_reset' view in Django?

I have set the following entry in the urls.py
(r'^password_reset/$', 'django.contrib.auth.views.password_reset'),
but once I go to http://127.0.0.1:8000/password_reset/ I get the error message:
NoReverseMatch at /password_reset/
Reverse for 'django.contrib.auth.views.password_reset_done' with arguments '()' and keyword arguments '{}' not found.
I was expecting password_reset_done view also to be coming out of the box. So what am I supposed to do at this stage?
UPDATE
After trying Blair's solution, I got a step closer.
(r'^password_reset_done/$', 'django.contrib.auth.views.password_reset_done'),
According to the book 'Django 1.0 Website Development', these built-in views should be used out of the box without further hassle. But maybe it has changed since Django 1.0...
Would be great if someone could shed light on this. Thanks
I have finally found the solution. I think there is always the slight misunderstanding between MVC and MTV pattern. In MTV (Django) the View stands for the controller and the Template stands for the View.
Hence while its true that the change password "Views" are coming built-in out-of-the-box, the actual templates (look & feel) still needs to be generated by the user while the underlying form (widget) is generated by Django automatically. It gets more clear when looking at the code.
Therefore add these two lines to url.py
(r'^change-password/$', 'django.contrib.auth.views.password_change'),
(r'^password-changed/$', 'django.contrib.auth.views.password_change_done'),
Then Under myproject/templates/registration add these two files
password_change_done.html
{% extends "base.html" %}
{% block title %}Password Change Successful{% endblock %}
{% block head %}Password Change Completed Successfully{% endblock %}
{% block content %}
Your password has been changed successfully. Please re-login with your new credentials
login or go back to the
main page.
{% endblock %}
password_change_form.html
{% extends "base.html" %}
{% block title %}Change Registration{% endblock %}
{% block head %}Change Registration{% endblock %}
{% block content %}
<form method="post" action=".">
{{form.as_p}}
<input type="submit" value="Change" />
{% csrf_token %}
</form>
{% endblock %}
Django needs to know which URL to redirect the user to once they have completed the form on the password_reset page. So add another line to your URL configuration:
(r'^password_reset_done/$', 'django.contrib.auth.views.password_reset_done'),
As of django 1.11 password_change view is deprecated.
Deprecated since version 1.11: The password_change function-based view should be replaced by the class-based PasswordChangeView.
What worked for me was:
In urls.py
from django.contrib.auth import views as auth_views
...
url('^account/change-password/$',
auth_views.PasswordChangeView.as_view(
template_name='registration/passwd_change_form.html'),
name='password_change'),
url(r'^account/password-change-done/$',
auth_views.PasswordChangeDoneView.as_view(
template_name='registration/passwd_change_done.html'),
name='password_change_done'),
And then add the couple of templates passwd_change_form.html and passwd_change_done.html under registration.
Note that I'm not using the default name, for some reason when I did that it defaulted to the django admin views.

How does the {{ form }} tag work in Django-registration app

I downloaded and installed django-registration app. I also downloaded a template that has this strange piece of code
{{ form }}
that magically creates 4 labels and 4 textboxes for the user to enter his registration information. How does it work?
{% extends "registration/registration_base.html" %}
{% block title %}Register for an account{% endblock %}
{% block content %}
<table>
<form method='post' action=''>{% csrf_token %}
{{ form }}
<tr><td></td><td><input type="submit" value="Send activation email" /></td>
</form>
</table>
{% endblock %}
It is part of django forms. See the documentation for more info.
https://docs.djangoproject.com/en/1.3/topics/forms/
If you are really interested check out the source code.
https://code.djangoproject.com/browser/django/trunk/django/forms
A django form (but other objects, too) has a unicode method, which is invoked, when a string representation of the object is requested. As you can see in the code, it just passes the call on to as_table - which in turn uses a generic helper function: _html_output. This basically loops over all the fields and constructs the HTML which then is returned and displayed on the page.

Categories

Resources