Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django can't find views...page not found error

I am trying to print a response from the view.. but django shows the page not found error(404)

My main project.urls are:-

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from . import views

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'ultimatefinalblog.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),
    url(r'^$',views.siteindex,name="siteindex"),
    url(r'^blog/', include('blog.urls')),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^markdown/', include('django_markdown.urls')),

)

my blog's urls.py are:-

from django.conf.urls import patterns,  url
from blog import views

urlpatterns = patterns('',
    #url(r'^$', views.BlogIndex.as_view(), name="index"),
    #url(r'^(?P<slug>\S+)$', views.BlogDetail.as_view(), name="entry_detail"),
    #url(r'^$', views.testview, name="testview"),
    url(r'^$', views.index, name="index"),
    url(r'^(?P<slug>\S+)$', views.detail, name="entry_detail"),
    url(r'^testingpage/', views.testview, name='testview'),
    )

I have defined the testview function in my views.py

def testview(request):
    return HttpResponse("testing our view!")

When i try to run the url 127.0.0.1:8000/blog/testingpage in my development server it shows the page not found error...can somebody help me solve this problem?

like image 984
Anshdeep singh Avatar asked May 15 '15 18:05

Anshdeep singh


2 Answers

Here is your issue:

In your URL patterns,

url(r'^(?P<slug>\S+)$', views.detail, name="entry_detail"),
url(r'^testingpage/', views.testview, name='testview'),

The testingpage is being matched with ?P<slug>\S+ (for views.detail), before views.testview, and you probably have a raise 404 or something similar line of code to match slug.

So, Change the order:

url(r'^testingpage/', views.testview, name='testview'),
url(r'^(?P<slug>\S+)$', views.detail, name="entry_detail"),

And it should work for you.

Also, Slug is generally matched with (?P<slug>[\w-]+) and not \S+

like image 161
karthikr Avatar answered Oct 21 '22 09:10

karthikr


So! I succeded to make your code work.

I'll organize this answer in three parts (beware : It will be exhaustive!) :

  • First :

I'll copy the code I made (almost the same as yours, plus the parts you didn't provide and I had to recode - these are very basic, just to fill the missing parts). I hope it will help you to find how to fix your problem by comparing. I'll also give an hypothesis about your problem.

  • Second :

I'll talk about your code. There are good habits that could help you to build your django projects (but you don't seem to use these). Please note that your code can work without using these. But it may be more difficult without these habits.

  • Third :

I will suggest a corrected version of your code with comments to illustrate the second part.

First - The code that works on my computer :

I make my own version of your project with django 1.7.5. I organized the project like this :

.
├── blog
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── main
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── views.py
│   └── wsgi.py
└── manage.py

Where "main" is the project name and "blog" an app.

From a fresh project, the files I had to modify/add are :

blog/urls.py :

from django.conf.urls import patterns,  url
from blog import views

urlpatterns = patterns('',
                       #url(r'^$', views.BlogIndex.as_view(), name="index"),
                       #url(r'^(?P<slug>\S+)$', views.BlogDetail.as_view(), name="entry_detail"),
                       #url(r'^$', views.testview, name="testview"),
                       url(r'^$', views.index, name="index"),
                       url(r'^(?P<slug>\S+)$', views.detail, name="entry_detail"),
                       url(r'^testingpage/', views.testview, name='testview'),
)

blog/views.py :

from django.shortcuts import render, HttpResponse

# Create your views here.

def testview(request):
    return HttpResponse("testing our view!")

def index(request):
    return HttpResponse("Index.")

def detail(request, slug="test"):
    return HttpResponse("Detail : " + slug)

main/urls.py :

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from . import views

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'main.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^$',views.siteindex,name="siteindex"),
    url(r'^blog/', include('blog.urls')),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^markdown/', include('django_markdown.urls')),
)

main/views.py :

from django.shortcuts import render, HttpResponse

# Create your views here.

def siteindex(request):
    return HttpResponse("site index!")

Then I just do :

>>>python manage.py migrate
>>>python manage.py runserver

And I can access to http://127.0.0.1:8000/blog/testingpage/ and to other pages. I have no problem this way.

But I you do so, you will see that this URL matches with the r'^(?P<slug>\S+)$' pattern. And therefore /blog/testingpage does not trigger the view testview but the view detail. So I think your problem may come from the detail view, could you add it to your question to check?

Second - How you could improve your code :

  • apps and views imports

The way you imports your views is functionnal, but it could be impractible You could add the app ("blog") containing your views to INSTALLED_APPS in your main/settings.py. And you will be able to use your views just by entering their names as strings.

edit :

This changed with the 1.8 release, now it's recommended to do like you did. My bad.

  • Your project isn't an app.

Your /main/urls.py suggests that you've a views.py in your /main directory. Using this directory this way isn't explicitly forbidden, but it's an app's purpose. the /main directory is meant to contain general settings. I think you should make a second app for your views.py (and probably some url patterns) if you don't want to insert it in the "blog" app.

  • urlpatterns order

With your blog/urls.py file, your app will "works". But /blog/testingpage/ will trigger the detail view and not the testview view, I'm not sure that is what you want to do. Beware the patterns order!

Third - An other way to do this :

Here is my version of the code. I have organized the project like this :

.
├── blog
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── main
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
└── website
    ├── __init__.py
    ├── admin.py
    ├── models.py
    ├── tests.py
    ├── urls.py
    └── views.py

The new files are :

blog/urls.py

from django.conf.urls import patterns, url
# You don't need this anymore
# from blog import views 

urlpatterns = patterns('blog.views',  # this first argument will be used as a prefix to locate your views.
                       url(r'^$', 'index' , name="index"),
                       # beware the order!
                       # url(r'^(?P<slug>\S+)$', views.detail, name="entry_detail"),
                       url(r'^testingpage/', 'testview', name='testview'),
                       url(r'^(?P<slug>\S+)$', 'detail', name="entry_detail"),
)

blog/views.py

from django.shortcuts import render, HttpResponse

# Create your views here.

def testview(request):
    return HttpResponse("testing our view!")

def index(request):
    return HttpResponse("Index.")

def detail(request, slug="test"):
    return HttpResponse("Detail : " + slug)

INSTALLED_APP in main/settings.py (/!\ Important /!\)

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
    'website',
)

main/urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'main.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^admin/', include(admin.site.urls)),
    url(r'^blog/', include('blog.urls')),
    url(r'^markdown/', include('django_markdown.urls')),
    url(r'^$', include('website.urls')),
)

website/urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
# If you add the app name to INSTALLED_APP you don't need this anymore.
# from . import views

urlpatterns = patterns('website.views', # This first argument will be used as a prefix to locate your views.
    url(r'^$', 'siteindex', name="siteindex"),
)

website/views.py

from django.shortcuts import render, HttpResponse

# Create your views here.

def siteindex(request):
    return HttpResponse("site index!")

I hope all of this will help.

like image 40
vmonteco Avatar answered Oct 21 '22 09:10

vmonteco