I am trying to add user uploadable images in my web app using Pillow. I created a Django Upload model and registered it in Admin. As soon as I added a photo using admin console I get the following error. Initially the website was working all fine
The Error
NoReverseMatch at /
Reverse for 'thing_detail' with arguments '()' and keyword arguments '{u'slug': ''}' not found. 1 pattern(s) tried: ['things/(?P<slug>[-\\w]+)/$']
Request Method: GET
Request URL: http://localhost:8000/
Django Version: 1.8.4
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'thing_detail' with arguments '()' and keyword arguments '{u'slug': ''}' not found. 1 pattern(s) tried: ['things/(?P<slug>[-\\w]+)/$']
Exception Location: /usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py in _reverse_with_prefix, line 496
Python Executable: /usr/bin/python
Python Version: 2.7.6
Python Path:
['/home/shashank/development/hellowebapp/hellowebapp',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PILcompat',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/pymodules/python2.7',
'/usr/lib/python2.7/dist-packages/ubuntu-sso-client']
Server time: Sun, 13 Mar 2016 18:54:31 +0000
Urls.py
from collection.backends import MyRegistrationView
from django.conf.urls import include, url
from django.contrib import admin
from collection import views
from django.conf import settings
from django.views.generic import TemplateView
from django.contrib.auth.views import (
password_reset,
password_reset_done,
password_reset_confirm,
password_reset_complete
)
urlpatterns = [
url(r'^$', views.index, name='home'),
url(r'^about/$',TemplateView.as_view(template_name='about.html'),name='about'),
url(r'^contact/$',TemplateView.as_view(template_name='contact.html'),name='contact'),
url(r'^things/(?P<slug>[-\w]+)/$','collection.views.thing_detail',name='thing_detail'),
url(r'^things/(?P<slug>[-\w]+)/edit/$','collection.views.edit_thing',name='edit_thing'),
url(r'^things/(?P<slug>[-\w]+)/edit/weight$','collection.views.edit_weight',name='edit_weight'),
url(r'^things/(?P<slug>[-\w]+)/delete/weight$','collection.views.remove_weight',name='remove_weight'),
#WORKING url(r'^things/(?P<pk>\d+)/remove/$', 'collection.views.remove_weight', name='remove_weight'),
url(r'^things/$',TemplateView.as_view(template_name='weight_removed.html'),name='weight_removed'),
url(r'^(?P<slug>[\w\d-]+)/(?P<pk>\d+)/$','collection.views.remove_weight',name='remove_weight'),
#url(r'^edit/(?P<slug>\d+)/weights$', 'collection.views.AddWeight',name='AddWeight'),
# the new password reset URLs
url(r'^accounts/password/reset/$',password_reset,{'template_name':'registration/password_reset_form.html'},name="password_reset"),
url(r'^accounts/password/reset/done/$',password_reset_done,{'template_name':'registration/password_reset_done.html'},name="password_reset_done"),
url(r'^accounts/password/reset/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',password_reset_confirm,{'template_name':'registration/password_reset_confirm.html'},name="password_reset_confirm"),
url(r'^accounts/password/done/$',password_reset_complete,{'template_name':'registration/password_reset_complete.html'},name="password_reset_complete"),
#setup additional registeration page
url(r'^accounts/register/$',MyRegistrationView.as_view(),name='registration_register'),
url(r'^accounts/create_thing/$','collection.views.create_thing',name='registration_create_thing'),
url(r'^accounts/',include('registration.backends.default.urls')),
url(r'^admin/', include(admin.site.urls)),
]
if settings.DEBUG:
urlpatterns += [
url(r'^media/(?P<path>.*)$','django.views.static.serve',{'document_root': settings.MEDIA_ROOT,}),
]
Models .py
from django.db import models
from django.contrib.auth.models import User
from django.db import models
from django.utils import timezone
class Thing(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
slug = models.SlugField(unique=True)
user = models.OneToOneField(User, blank=True, null=True)
class Weight(models.Model):
date = models.DateTimeField(default=timezone.now)
weight_value = models.CharField(max_length=255)
thingRA = models.ForeignKey(Thing,related_name="weights")
class Meta:
order_with_respect_to = 'thingRA'
ordering = ['date']
def get_image_path(instance, filename):
return '/'.join(['thing_images', instance.thing.slug, filename])
class Upload(models.Model):
thing = models.ForeignKey(Thing, related_name="uploads")
image = models.ImageField(upload_to=get_image_path)
Admin.py
from django.contrib import admin
# import your model
from collection.models import Thing, Weight, Upload
class ThingAdmin(admin.ModelAdmin):
model = Thing
list_display = ('name', 'description',)
prepopulated_fields = {'slug': ('name',)}
# and register it
admin.site.register(Thing, ThingAdmin)
class WeightAdmin(admin.ModelAdmin):
model = Weight
list_display = ('date','weight_value',)
admin.site.register(Weight, WeightAdmin)
class UploadAdmin(admin.ModelAdmin):
list_display = ('thing', )
list_display_links = ('thing',)
# and register it
admin.site.register(Upload, UploadAdmin)
Base.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<title>
{% block title %}
WEB PAGE BY SHASHANK
{% endblock title %}
</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}" />
</head>
<body>
<div id="page">
<div id="logo">
<h1>S PORTAL</h1>
</div>
<div id="nav">
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
{% if user.is_authenticated %}
<li>Logout</li>
<li>My Profile</li>
{% else %}
<li>Login</li>
<li>Register</li>
{% endif %}
</ul>
</div>
{% block content %}{% endblock content %}
<div id="footer">
<p>
Webpage made by SHASHANK
</p>
</div>
</div>
</body>
</html>
View.py
from django.shortcuts import render,redirect,get_object_or_404
from collection.models import Thing, Weight
from collection.forms import ThingForm, WeightForm, ThingWeightFormSet
from django.template.defaultfilters import slugify
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.views.decorators.csrf import csrf_protect
from django.views.generic import ListView, CreateView, UpdateView
from django import forms
def index(request):
things = Thing.objects.all()
return render(request,'index.html',{'things':things,})
def thing_detail(request, slug):
# grab the object...
thingRA = Thing.objects.get(slug=slug)
weights = thingRA.weights.all().order_by('-date')
# and pass to the template
return render(request, 'things/thing_detail.html', {'thing': thingRA, 'weights':weights,})
def edit_thing(request, slug):
# grab the object
thing = Thing.objects.get(slug=slug)
# set the form we're using
form_class = ThingForm
# if we're coming to this view from a submitted form
if request.method == 'POST':
# grab the data from the submitted form and apply to
# the form
form = form_class(data=request.POST, instance=thing)
if form.is_valid():
# save the new data
form.save()
return redirect('thing_detail', slug=thing.slug)
# otherwise just create the form
else:
form = form_class(instance=thing)
# and render the template
return render(request, 'things/edit_thing.html', {'thing': thing,'form': form,})
def create_thing(request):
form_class = ThingForm
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
thing = form.save(commit=False)
thing.user = request.user
thing.slug = slugify(thing.name)
thing.save()
slug = slugify(thing.name)
return redirect('thing_detail', slug=thing.slug)
else:
form = form_class()
return render(request,'things/create_thing.html', {'form': form,})
def edit_weight(request, slug):
thing = get_object_or_404(Thing, slug=slug)
if request.method == "POST":
form = WeightForm(request.POST)
if form.is_valid():
weight = form.save(commit=False)
weight.thingRA = thing
weight.save()
return redirect('thing_detail', slug=thing.slug)
else:
form = WeightForm()
return render(request, 'things/edit_weight.html', {'form': form})
"""WORKING WEIGHT
def remove_weight(request, pk):
weight = get_object_or_404(Weight, pk=pk)
thing_pk = weight.thingRA.pk
weight.delete()
return redirect('weight_removed')
"""
def remove_weight(request, pk, slug):
weight = get_object_or_404(Weight, pk=pk)
thing = get_object_or_404(Thing, slug=slug)
thing_pk = weight.thingRA.pk
weight.delete()
return redirect('thing_detail', slug=slug)
#login_required
def edit_thing(request, slug):
# grab the object...
thing = Thing.objects.get(slug=slug)
# make sure the logged in user is the owner of the thing
if thing.user != request.user:
raise Http404
# set the form we're using...
form_class = ThingForm
# if we're coming to this view from a submitted form,
if request.method == 'POST':
# grab the data from the submitted form and
# apply to the form
form = form_class(data=request.POST, instance=thing)
if form.is_valid():
# save the new data
form.save()
return redirect('thing_detail', slug=thing.slug)
# otherwise just create the form
else:
form = form_class(instance=thing)
# and render the template
return render(request, 'things/edit_thing.html', {'thing': thing,'form': form,})
I would say that you have a Thing with slug="". You can check this out using django shell:
from yourapp.models import Thing
Thing.objects.get(slug='')
According to your model definition slug can be blank, but your url pattern does not accept blank slug. You will have to fix either your slug field or your url pattern.
You're probably using a {% url 'thing_detail' slug=thing.slug %} in your template with a 'thing' object that has an empty slug attribute.
Either add a conditional to your template that checks for an existing slug in the object so that the template tag isn't invoked or make sure that none of your Thing objects have a blank slug.
Finally figured it out. The problem was nowhere in the code. Actually all I needed was to logout from the admin panel in Django. Since being logged in the Admin panel prevented other Users to interact with their related data.
Related
Im trying to implement a chat-function for my website. In order to do that, i followed the following tutorial: https://channels.readthedocs.io/en/latest/tutorial/
I've then changed the code a little bit in order to implement it. Until here, everything works just fine. Now I want to store the form-data inside of a database, and thats where the problem appears.
But first my code:
urls.py:
from django.urls import path
from .views import ChatOverView
urlpatterns = [
path('<int:pk>/', ChatOverView.as_view(), name='chat-explicit'),
path('', ChatOverView.as_view(), name='chat-home'),
]
views.py (theres much code here that is probably not needed for this question, but since i dont know what part of it i can ignore, im just posting the whole file-content):
from django.views.generic import ListView
from django.views.generic.edit import FormMixin, FormView
from django.db.models import Q
from django.urls import resolve
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from .models import Message
from .forms import MessageRegisterForm
class ChatOverView(ListView, FormMixin):
model = Message
template_name = 'chat/home-chat.html'
form_class = MessageRegisterForm
success_url = '/thanks/'
def form_valid(self, form):
form = self.get_form()
if form.is_valid():
data = form.cleaned_data
return super().form_valid(form)
def get_context_data(self, *args, **kwargs):
context = super(ChatOverView, self).get_context_data(*args, **kwargs)
messages_raw = reversed(Message.objects.filter(Q(sender=self.request.user) | Q(receiver=self.request.user)))
messages = {}
for mes in messages_raw:
# i am receiver
if mes.sender != self.request.user:
if mes.sender in messages:
messages[mes.sender].append({"received": mes})
else:
messages.update({mes.sender: [{"received": mes}]})
# i sent
else:
if mes.receiver in messages:
messages[mes.receiver].append({"sent": mes})
else:
messages.update({mes.receiver: [{"sent": mes}]})
active_user = self.get_active_chat(messages)
chatroom_name = self.get_chatroom_name(active_user)
context.update(messages_data=messages, active=active_user, roomname=chatroom_name)
return context
def get_chatroom_name(self, active_chat):
# my convention
ids = [active_chat.id, self.request.user.id]
ids.sort()
return str(ids[0]) + '_' + str(ids[1])
def get_active_chat(self, messages):
url_name = resolve(self.request.path_info).url_name
if url_name == "chat-home":
return list(messages.keys())[0]
else:
pk_user = self.request.build_absolute_uri().split("/")[-2]
user = get_object_or_404(User, pk=pk_user)
return user
home-chat.html:
{% extends "solawi/base.html" %}
{% load define_dictfilters %}
{% block content %}
<form class="bg-light" method="post">
<div class="input-group">
{% csrf_token %}
{{ form }}
<div class="input-group-append">
<button type="submit" id="chat-message-submit" value="enter">send</button>
</div>
</div>
</form>
{% endblock content %}
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Message(models.Model):
sender = models.ForeignKey(User, related_name="sender", on_delete=models.CASCADE)
receiver = models.ForeignKey(User, related_name="receiver", on_delete=models.CASCADE)
content = models.TextField()
date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.sender.username + ' to ' + self.receiver.username
The rest of the files/settings entrys are the same as in the tutorial linked above.
Now comes the problem: when submitting the form, i get the following error:
Method Not Allowed (POST): /chat/
Method Not Allowed: /chat/
HTTP POST /chat/ 405 [0.00, 127.0.0.1:54424]
How can i fix it?
Thank you for your Help!!
ListView implements a get() method, but no post() method. You need to implement a post() method in order for the view to allow POST requests.
You could subclass django.views.generic.ProcessFormView to get this, or, if you really need a ListView, then you can add a post() method to the class which handles the form validation and whatever else you need to do. Here is how ProcessFormView implements it:
def post(self, request, *args, **kwargs):
"""
Handle POST requests: instantiate a form instance with the passed
POST variables and then check if it's valid.
"""
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
I'm very new to Django and part of the assignment was to create our own blog model form. I followed the previous examples of the youtube tutorial but was unable to create my own blog model form. The form will not save because it's invalid and I have been busting my head for 2 days to solve it but can't find what is wrong.
Also, every time I submit my form, it redirects me to another page which I don't quite understand why.
Please help.
I'm using Django version 2.0.7.
My models.py
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=120) # Max length required
content = models.TextField()
active = models.BooleanField(default=True)
My forms.py
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = [
'title',
'content',
'active'
]
my views.py
from django.shortcuts import render, get_object_or_404, redirect
from .forms import ArticleForm
from .models import Article
def article_list_view(request):
print("this is article_list.html")
queryset = Article.objects.all()
context ={
"object_list": queryset
}
return render(request, "blogs/article_list.html", context)
def article_create_view(request):
form = ArticleForm(request.POST or None)
print(ArticleForm.errors)
if form.is_valid():
print("Valid form")
form.save()
else:
print("invalid")
print(ArticleForm.errors)
context = {
"form": form
}
return render(request, "blogs/article_create.html", context)
article_create.html
{% extends 'base.html' %}
{% block content %}
<form action='.' method='POST'>{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Save'>
</form>
{% endblock %}
urls.py
from django.contrib import admin
from django.urls import include, path
from pages.views import (
home_view,
contact_view,
about_view,
social_view
)
from blog.views import (
article_list_view,
article_detail_view,
article_create_view
)
urlpatterns = [
path('products/', include('products.urls')),
path('', home_view, name='home'),
path('contact/', contact_view, name='contact'),
path('about/', about_view, name='product-detail'),
path('social/', social_view, name='social'),
path('admin/', admin.site.urls),
#blog paths
path('articles/', article_list_view, name = 'articles'),
path('articles/detail/<int:id>', article_detail_view, name = 'article-detail'),
path('articles/create', article_create_view, name = 'article-create'),
]
This shows up on my command prompt of my server:
Django version 2.0.7, using settings 'trydjango.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
<property object at 0x000001ED94386458>
invalid
<property object at 0x000001ED94386458>
[18/Apr/2019 22:33:51] "GET /articles/create HTTP/1.1" 200 920
this is article_list.html
[18/Apr/2019 22:34:02] "POST /articles/ HTTP/1.1" 200 668
As soon as I land onto the articles/create or article_create.html, the <property object at 0x000001ED94386458> shows up.
1) You should not use .errors on the class.
ArticleForm.errors
should be
form.errors
2) You should separate your GET and POST requests in your view.
def article_create_view(request):
if request.method == "POST":
form = ArticleForm(request.POST)
if form.is_valid():
print("Valid form")
form.save()
else:
print("Invalid form")
print(form.errors)
else:
form = ArticleForm()
context = {"form": form)
return render(request, "blogs/article_create.html", context)
Your form should be posting to "", not ".".
<form action='' method='POST'>{% csrf_token %}
Alternatively/additionally, make sure you originally navigate to /articles/create/, not /articles/create without the final slash. (Although normally the built-in CommonMiddleware will take care of redirecting to the path with the slash - have you set the APPEND_SLASH setting to False by any chance? Don't.)
I just don't understand. I've spent too much time on this error. Please help me pinpoint the issue. Let me know if you need any other information.
Error reads:
NoReverseMatch at /login/here/
Reverse for 'welcome' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
Project urls.py
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
# creating registered namespaces for each app
url(r'^login/', include('login_app.urls', namespace = "login_app")),
]
login_app/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'here/', views.login_user),
]
login_app/views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from login_app.forms import LoginForm
from django.shortcuts import render_to_response # this is going to be depricated
from django.template import RequestContext
def login_user(request):
form = LoginForm()
logout(request) # logs out user upon reaching the /login/ page
user = password = ''
# if this is a POST request we need to process the form data
if request.POST:
# create a form instance and populate it with the data from the request:
form = LoginForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
user = form.cleaned_data['user'] # extracting the username from the form before authenticating
password = form.cleaned_data['password'] # extracting the password from the form before authenticating
user = authenticate(username=user, password=password) # authenticating
if user is not None:
login(request, user)
#return HttpResponseRedirect(reverse('dashboard_app:welcome'))
return HttpResponse("hi!")
else:
template = 'login.html'
state = "Your username and/or password are incorrect."
context = {'state': state,'form': form,}
return render(request, template, context)
template = 'login_app/login.html'
state = ''
context ={'state': state, 'form': form}
#return HttpResponse("hey!")
return render(request, template, context)
login.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'login_app/css/login.css' %}">
<div class="container-fluid">
<div class="well">
{% csrf_token %}
{% crispy form %}<br>
<!--error handling-->
<p>{{ state }}</p>
</div>
</div>
{% endblock %}
login_app/forms.py
from django import forms
## importing crispy form utilities
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Div, ButtonHolder
from crispy_forms.bootstrap import FormActions, PrependedText
class LoginForm(forms.Form):
## user field
user = forms.CharField()
## password field
password = forms.CharField(
widget=forms.PasswordInput()
)
## Using crispy forms to create a form
helper = FormHelper()
helper.form_method = 'POST'
helper.form_show_labels = False
helper.layout = Layout(
Div(
PrependedText('user', '<i class="fa fa-user fa-fw"></i>', placeholder='Username'),
PrependedText('password', '<i class="fa fa-lock fa-fw"></i>', placeholder='Password', autocomplete='off'),
style='padding:0px;',
css_class='col-md-3'
),
Div(
ButtonHolder(
Submit('submit','Login'), css_class='col-md-12'
), css_class='row'
)
)
So for future reference here's what happened....
The base.html (which I didn't post) had this line in it.
<a class="navbar-brand" href="#">Clinical Molecular Incident Reporting System</a> <!-- {% url 'login_app:welcome' %}-->
The mistake here was I assumed the commenting out of html <!----> would also apply to Django's inline rendering syntax {%%}, but it didn't (Looking back on this, I have no idea why I thought that). Deleted the html comment and viola! I spend a lame forever amount of time solving this problem. Hopefully this will be of use to someone later.
Thanks to #Transformer for working to solve my issue.
I am a newbie for Django and working on a project. I am stucked with setting up a forms.py and integrate the same with my template. I did all the required things with the help of all sort of tutorial I got online but I was unable to see the fields I declared in form on the HTML Page. Below is the code I used for each of the module. It would be great if anyone can help me out with this.
models.py
from django.db import models
class EarlyBirds(models.Model):
name = models.CharField(max_length=200)
email = models.CharField(max_length=200)
contact_number = models.IntegerField()
def __str__(self):
return '%s - %s' % (self.name, self.email)
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import RequestContext, loader
from django.shortcuts import render_to_response
from .forms import EarlyBirdsForm
from .models import EarlyBirds
def register(request):
context = RequestContext(request)
success=''
if request.method == 'POST':
form = EarlyBirdsForm(request.POST)
if form.is_valid():
name = request.POST.get('name','')
email = request.POST.get('email','')
number = request.POST.get('number','')
if email:
email_exist = EarlyBirds.objects.filter(email=email)
if email_exist:
success = 'Thankyou for your intrest! This email is already registered with us. We will get back to you soon.'
else:
eb_obj = EarlyBirds(name=name,email=email,contact_number=number)
eb_obj.save()
success = 'Thankyou for your intrest! We will get back to you soon.'
else:
success = 'Please fill out the required fields'
else:
success = form.errors
else:
form = EarlyBirdsForm()
return render_to_response('ComingSoon.html', {'success':success}, context)
forms.py
from django import forms
from django.forms import ModelForm
from app_name.models import EarlyBirds
class EarlyBirdsForm(forms.Form):
name = forms.CharField(required=True,max_length=100)
email = forms.CharField(required=True,max_length=100)
number = forms.IntegerField(required=True)
class Meta:
model = EarlyBirds
fields = ("name", "email", "number")
template
<html xmlns="http://www.w3.org/1999/xhtml">
<body align="center">
<form method="POST" action="{%url 'comingsoon:register'%}">
{% csrf_token %}
<div class="header-blog-comingSoon" align="center">
<!--<form method="post">
<span>{{ form.as_p }}</span>
<br/>
<span><button class="comingsoon-Reg" type="submit">Register</button></span>
<br/><br/>
<br/><label class="successLabel">{{success}}</label>
</div>
</form>
</body>
</html>
project.urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^ComingSoon/', include('app_name.urls', namespace="comingsoon")),
url(r'^admin/', include(admin.site.urls)),
]
When I try to execute this code, the all I was able to see in the "Register" button on my html page. The three text fields for Name, Email and Contact number were missing. Please let me know what I am missing over here.
You forgot to add the form to your context:
def register(request):
...
return render_to_response('ComingSoon.html', {'success':success, 'form': form}, context)
Maybe you should try writing your form like this:
class EarlyBirdsForm(forms.ModelForm):
class Meta:
model = EarlyBirds
fields = '__all__'
Much easier and simpler. Since you're using all the attributes in the model, might as well connect the form directly with the model.
And César Bustíos said it right. You didn't add the form in the context dictionary for your template.
I am pretty new to Django but have gone through a few tutorials and have taken it upon myself to create an app very similar to the Tango with Django walkthrough app, rango.
Everything has worked so far, but when I attempt to add a registration feature, the link brings me to the wrong template. I think this be because I have migrated parts from another app and so perhaps the webpage is looking for something that isn't there?
Here is my forms.py:
from django import forms
from django.contrib.auth.models import User
from address_book.models import Client, UserProfile
class ClientForm(forms.ModelForm):
name = forms.CharField(max_length=128, help_text="Name: ")
phone = forms.IntegerField(help_text="Phone Number: ")
address = forms.CharField(max_length=128, help_text="Address: ")
desired_weight = forms.IntegerField(help_text="Desired Weight: ")
start_weight = forms.IntegerField(help_text="Start Weight: ")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
slug = forms.CharField(widget=forms.HiddenInput(), required=False)
comments = forms.CharField(max_length=500, help_text="Comments: ")
# An inline class to provide additional information on the form.
class Meta:
# Provide an association between the ModelForm and a model
model = Client
fields = ('name', 'phone', 'address', 'desired_weight', 'start_weight',)
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('website', 'picture')
models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Client(models.Model):
name = models.CharField(max_length=128, unique=True)
phone = models.IntegerField(default=0)
desired_weight = models.IntegerField(default=0)
start_weight = models.IntegerField(default=0)
address = models.CharField(max_length=128, blank=True)
comments = models.CharField(max_length=500, blank=True)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Client, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
website = models.URLField(blank=True)
picture = models.ImageField(upload_to='profile_images', blank=True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
views.py
from django.http import HttpResponse
from django.shortcuts import render
from address_book.forms import ClientForm, UserForm, UserProfileForm
from address_book.models import Client
def index(request):
client_list = Client.objects.all().order_by('name')
# Construct a dictionary to pass to the template engine as its context.
# Note the key boldmessage is the same as {{ boldmessage }} in the template!
context_dict = {'clients': client_list}
# Return a rendered response to send to the client.
# We make use of the shortcut function to make our lives easier.
# Note that the first parameter is the template we wish to use.
return render(request, 'address_book/index.html', context_dict)
def add_client(request):
# A HTTP POST?
if request.method == 'POST':
form = ClientForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save(commit=True)
# Now call the index() view.
# The user will be shown the homepage.
return index(request)
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = ClientForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render(request, 'address_book/add_client.html', {'form': form})
def client(request, client_name_slug):
# Create a context dictionary which we can pass to the template rendering engine.
context_dict = {}
try:
# Can we find a category name slug with the given name?
# If we can't, the .get() method raises a DoesNotExist exception.
# So the .get() method returns one model instance or raises an exception.
client = Client.objects.get(slug=client_name_slug)
context_dict['client_name'] = client.name
context_dict['client_name_slug'] = client_name_slug
context_dict['client_phone'] = client.phone
context_dict['client_address'] = client.address
context_dict['desired_weight'] = client.desired_weight
context_dict['start_weight'] = client.start_weight
context_dict['comments'] = client.comments
# Retrieve all of the associated pages.
# Note that filter returns >= 1 model instance.
# pages = Page.objects.filter(category=category)
# Adds our results list to the template context under name pages.
# context_dict['pages'] = pages
# We also add the category object from the database to the context dictionary.
# We'll use this in the template to verify that the category exists.
context_dict['client'] = client
except Client.DoesNotExist:
# We get here if we didn't find the specified category.
# Don't do anything - the template displays the "no category" message for us.
pass
# Go render the response and return it to the client.
print context_dict
return render(request, 'address_book/client.html', context_dict)
def register(request):
# A boolean value for telling the template whether the registration was successful.
# Set to False initially. Code changes value to True when registration succeeds.
registered = False
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information.
# Note that we make use of both UserForm and UserProfileForm.
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
# If the two forms are valid...
if user_form.is_valid() and profile_form.is_valid():
# Save the user's form data to the database.
user = user_form.save()
# Now we hash the password with the set_password method.
# Once hashed, we can update the user object.
user.set_password(user.password)
user.save()
# Now sort out the UserProfile instance.
# Since we need to set the user attribute ourselves, we set commit=False.
# This delays saving the model until we're ready to avoid integrity problems.
profile = profile_form.save(commit=False)
profile.user = user
# Did the user provide a profile picture?
# If so, we need to get it from the input form and put it in the UserProfile model.
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
# Now we save the UserProfile model instance.
profile.save()
# Update our variable to tell the template registration was successful.
registered = True
# Invalid form or forms - mistakes or something else?
# Print problems to the terminal.
# They'll also be shown to the user.
else:
print user_form.errors, profile_form.errors
# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
user_form = UserForm()
profile_form = UserProfileForm()
# Render the template depending on the context.
return render(request,
'address_book/register.html',
{'user_form': user_form, 'profile_form': profile_form, 'registered': registered} )
register.html
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}Register{% endblock %}
{% block body_block %}
<h1>Register with 3010 Weightloss !</h1>
{% if registered %}
Return to the homepage.<br />
{% else %}
Rango says: <strong>register here!</strong><br />
<form id="user_form" method="post" action="/address_book/register/"
enctype="multipart/form-data">
{% csrf_token %}
<!-- Display each form. The as_p method wraps each element in a paragraph
(<p>) element. This ensures each element appears on a new line,
making everything look neater. -->
{{ user_form.as_p }}
{{ profile_form.as_p }}
<!-- Provide a button to click to submit the form. -->
<input type="submit" name="submit" value="Register" />
</form>
{% endif %}
{% endblock %}
urls.py
from django.conf.urls import patterns, url
from address_book import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^add_client/$', views.add_client, name='add_client'),
url(r'^(?P<client_name_slug>[\w\-]+)/$', views.client, name='client'),
url(r'^register/$', views.register, name = 'register'),
)
index.html
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}Index{% endblock %}
{% block body_block %}
<head>
<title>Rango</title>
</head>
<body>
<h2>Current Clients:</h2>
{% for client in clients %}
<li>{{ client.name }}</li>
{% endfor %}
</body>
{% endblock %}
and finally my base.html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Address_book</title>
</head>
<body>
{% block body_block %}{% endblock %}
</body>
<h2> Need to make changes? </h2>
<ul>
<li>Add new client</li>
<li>Register here</li>
</ul>
</html>
Like I said above, when I click the link to register in index.py, it brings me to another template, client.html.
It looks like the problem is that /address_book/register/ matches your client url, which comes before the register URL. To fix that, one way to fix this would be to switch the order of the URL strings:
# urls.py
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^add_client/$', views.add_client, name='add_client'),
url(r'^register/$', views.register, name = 'register'),
url(r'^(?P<client_name_slug>[\w\-]+)/$', views.client, name='client'),
)
However, it would be better to call the URL by its name in your base.html instead of relying on the order of the URL strings:
# base.html
...
<li>Register here</li>
...