Very new to django. I'm using version 1.5.2 and I just did a fresh install. I'm using the django development server; I'll be moving to Apache down the road, but I want to understand the django's particular flavor of MVC methodology before doing taking that step.
So I start up the django server with `python manage.py runserver 0.0.0.0:8000' through the terminal in my project directory (django_books). I get this error:
ViewDoesNotExist at /
Could not import django_books.views.home. Parent module django_books.views does not exist.
So my view doesn't exist. My view.py file is empty because the tutorial I was following did not include one. I'm not sure if this is the problem. If it is, how do I create this file (what goes in it)?
Directory Structure:
django_books
beer (from the tutorial lol)
migrations
__init__.py
models.py
views.py
random_book
(same as beer above)
django_books (this is my actual django project, beer and random_book are apps)
__init__.py
settings.py
urls.py
wsgi.py
media
.gitignore
manage.py
requirements.txt (output from pip freeze command)
urls.py
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'django_books.views.home', name='home'),
# url(r'^django_books/', include('django_books.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
)
If you keep your urls.py the way it is, that means you need to create views.py within /django_books/django_books/
Within that file, create a new function called home.
Alternately, if you have any functions inside of /django_books/beer/, you could reference them from urls.py.
All urls.py does is expose a python path to a function and route a URL there. So you can see that you don't have a module or file called views within django_books/django_books, which is why you get the failure.
View is basically a python function that receives HTTP Request and returns HTTP Response.
Quote from docs:
A view function, or view for short, is simply a Python function that
takes a Web request and returns a Web response. This response can be
the HTML contents of a Web page, or a redirect, or a 404 error, or an
XML document, or an image . . . or anything, really. The view itself
contains whatever arbitrary logic is necessary to return that
response. This code can live anywhere you want, as long as it’s on
your Python path. There’s no other requirement–no “magic,” so to
speak. For the sake of putting the code somewhere, the convention is
to put views in a file called views.py, placed in your project or
application directory.
This line url(r'^$', 'django_books.views.home', name='home'), in urls.py points the index / of your site to the home view - you should create it.
Create a python function called home in views.py:
from django.http import HttpResponse
import datetime
def home(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
Restart your development server and visit http://127.0.0.1:8000.
FYI, read the tutorial more carefully, part 3 is about dealing with urls and views.
Related
I just started learning django and running the tutorial part 3, decided to see if I understood the mapping from urls.py to views.py.
I got views and urls to work in the polls app, but then I wanted to make views in the project folder, so I made a views.py file in the project folder (see code below), with a view/function , which I named 'home'.
I then edited the urls.py in the project-folder(see below). run the server, It worked! visiting the url: http://localhost:8000/
it responded:
Hello, world. You're at the HOME PAGE.
BUT.. when I tried to make another view in same views.py called: morn, and adding the url for it, then error (see below),
http://localhost:8000/morn
returning:
localhost refused to connect.
I DID IT EXACTLY THE SAME WAY, so just when I thought I understood it, I didnt get it at all?!?!
The difference between the two views are just their name and path, why doesnt it work then?
on a linux manjaro
Python 3.8.1
Django 3.0.3
#
#this is my urls.py (which I made myself), in the project folder
from django.urls import include, path
from django.contrib import admin
from . import views
#from views import morn
admin.autodiscover()
urlpatterns = [
#lager en index-side
path('', views.home, name='home'),
path('morn/', views.morn, name='morn'),
path('admin/', admin.site.urls, name='admin'),
path('polls/', include('polls.urls')),
]
#
#this is the views.py in myproject folder, same folder as
from django.http import HttpResponse
def home(request):
output = 'Hello, world. You\'re at the HOME PAGE.'
return HttpResponse(output)
def morn(request):
output = 'Hello, world. Youre at the morn-path.'
return HttpResponse(output)
ERROR from konsole running the morn-view:
File "/home/nr1/dev/django/myproject/myproject/urls.py", line 29, in <module>
path('morn/', views.morn, name='morn'),
AttributeError: module 'myproject.views' has no attribute 'morn'
Oh no... I just got it! :)
I have put the views.py file in both of the myproject-folders and the urls.py is just in the inner myproject-folder. I was then updating just the outer views.py-file, when I thought I was in the inner views.py, so, ofcourse, the urls.py couldnt find the new function, it was searching the wrong views.py (outer one).
a lot of frustration for nothing.. but I learnt, I learnt!
In a django 1.8 project, I am attempting to redirect http://myProject/ads.txt to an external url http://a.location.that.has.the.ads.txt.file and thus serve the ads.txt file without using ftp to simply place the ads.txt in the root.
Given this minimal directory structure:
django projects
myProject
myapp
urls.py
views.py
someotherapp
yetanotherapp
myProject
settings.py
urls.py (this is the top urls.py)
views.py
in myProject/myProject/urls.py, (the “top” urls.py) I have as the first entry in the urlpatterns list, the lines:
urlpatterns = patterns('',
(r'^ads\.txt', RedirectView.as_view(url='http://a.location.that.has.the.ads.txt.file', permanent=False)),
followed by many more pattern matching regex’s. This does not work and fails with a 404. What does work is
urlpatterns = patterns('',
(r'^foo/ads\.txt', RedirectView.as_view(url='http://a.location.that.has.the.ads.txt.file', permanent=False)),
and then calling http://myProject/foo/ads.txt
Unfortunately, ads.txt files must be placed at the site root. I have tried many different regex’s that test fine in a regex validator, but just don’t work (returns 404). How do I do this without the extra dir “foo”? Any thoughts appreciated. Thank you.
Turns out you cannot redirect with the top level urls.py "routing table" to above the Django project root. A nginx server level redirect did the trick.
I have to include multiple changes to djangos admin panel, so I decided to fork the django admin app into my own django project.
As I was working with this admin app I recognized, that the site registration and template handling differs from the apps, that are normally created in django.
For instance, I want to keep the old admin index.html template and view, for backup and safety reasons but the landing page should be replaced by a custom page.
For that of course I need to change admin/templates/index.html and /admin/sites.py respectively.
I copied the old index function in admin/sites.py to old_index.py and created a old_index.html in the template folder.
But if I try to reference to old_index.html in my new index.html with
old index
I got an NoReverseMatch-Exception thrown. Unfortunately I did not found more information about how the django admin app itself register new views and sites, so an example or description would be helpful.
Creating separate views for the admin app in the distinct other apps in my project is no real option, due the high amount of changes, that need to be done.
The main urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'django_project.views.home', name='home'),
url(r'^polls/', include('other_app.urls', namespace="other_app")),
url(r'^admin/', include(admin.site.urls)),
)
The admin app itself does not provide a urls.py file and the views.py is exactely the same as in django.contrib.admin I just copied the function index to a new function called old_index, referencing to a template old_index.html.
Maybe the point did not get so clear, as I expected. I copied the whole admin app in my project and want to add a custom defined site to it, regardless where. But I failed to understand how sites and views are registered in the admin app itself, because the way is different from the custom apps you create normally in django.
So, is it possible (and how) to add a custom site in the django.contrib.admin app?
I think you need to create your own AdminSite for custom purposes and keep default as it is. More about this you can find here: https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#adminsite-objects and here https://docs.djangoproject.com/en/dev/ref/contrib/admin/#multiple-admin-sites-in-the-same-urlconf
Update:
You need to edit get_urls method of AdminSite class - add:
url(r'^$', wrap(self.old_index), name='old_index')
to urlpatterns variable. And rename old index method to old_index.
I'm new to Django 1.4 and try my first project. It's OK to create the app:
./manage.py startapp APP_NAME
and recognized by Django in urls.py as following:
(r'^home/$', 'APP_NAME.views.home'),
but when I only create a APP_NAME.py files in root directory of projects,and change the urls.py file as following:
(r'^home/$', 'APP_NAME.home'),
the debug page tell me ViewDoesNotExist. Even if I change the urls.py file to (with from...import and without single quotes):
from APP_NAME import home
(r'^home/$', home),
It also doesn't work.
How to solve it? It intricate to create APP for every view file.
Have you actually implemented your home function in 'APP_NAME.__init__.py'; if not, your code will not work, because there is nothing that can be called
python manage.py startapp news
In your created news directory there is a views.py. Now lets add something:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello")
now in your urls.py you add this:
(r'^news/$', 'news.index'),
Just start the devserver python manage.py runserver and point your browser to http://localhost:8000/news/
You should see "Hello".
Now you could add in your news/views.py some more stuff - like details, archive and so on.
Also be sure to have an empty __init__.py file in every directory you'd like to import.
from app.views import something will not work if there's no init-file within the app-directory.
I'm new to Django and working my way through "The Django Book" by Holovaty and Kaplan-Moss. I have a project called "mysite" that contains two applications called "books" and "contact." Each has its own view.py file. In my urls.py file I have the following:
from books import views
from contact import views
...
urlpatterns = patterns('',
...
(r'^search/$', views.search),
(r'^contact/$', views.contact),
...
When I run my code I get this error:
NameError at /search/
...
Exception value: 'module' object has no attribute 'search'
What I believe is happening is that since views from contact was imported last, Django is looking at contact's view which does not contain search (search is in books' view).
What is the proper way to import the views.py file from two distinct applications within a Django urls file?
Thanks for your help!
Disclaimer: Not a Django answer
The problem is with these two lines:
from books import views
from contact import views
The second import is shadowing the first one, so when you use views later you're only using the views from contact.
One solution might be to just:
import books
import contact
urlpatterns = patterns('',
...
(r'^search/$', books.views.search),
(r'^contact/$', contact.views.contact),
...
I'm not sure, but I also think that you don't actually need to import anything and can just use strings in your pattern, something like: 'books.views.search'.
Another possiblity is to follow Simon Visser suggestion:
from books.views import search
from contact.views import contact
from books import views
from contact import views
You are overwriting the name views. You need to import them as different names or as absolute names.
import books.views
import contact.views
... or ...
from books import views as books_views
from contact import views as contact_views
Then use the correct name when defining your URLs. (books.views.search or books_views.search depending on the method you choose)
The reason I’m answering this question is because it was answered years ago and those answers are not correct or useful anymore for newer Django versions, or there is a better practice you should know about.
So, if you have more than one app in your Django project then you should use a new urls.py file for every one of your apps. It means that if you start a new app then you have to manually create a new file called urls.py in the subfolder of your new app. Many beginners first do not understand why this is good, but this is a good practice if you plan creating more apps in one Django project.
When you start a project, the urls.py file automatically created in your project folder, but if you create/start a new app in Django, then it is a good practice if you create a separate urls.py for that app in its own folder. (And that way you will never have the "importing different app's views into urls.py" problem in the first place).
After you created the urls.py file for your app, then you have to include that app’s urls.py file in your project’s urls.py file in the following way:
Let’s see an example when you create a new app called ‘my_new_app’.
This is how your project’s main urls.py file should look like:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^my_new_app/', include('my_new_app.urls')),
]
In your project’s urls.py file you have to import the ‘include’ method, then you can include your my_new_app urls.py file in your project’s main urls.py file. In your my_new_app folder you have to manually create a urls.py file as I stated above. Then you have to use that file for all of your urlpatterns of your my_new_app. Then of course this way it’s going to be automatically included in your project’s main urls.py file.
So this is then how your my_new_app own urls.py file should look like:
from django.conf.urls import url
from my_new_app import views
urlpatterns = [
url(r'^$', views.index, name = "index"),
]
Assuming that you also created a first view called ‘index’ in your ‘my_new_app/views.py file.
my_new_app/views.py file look like this:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello World!")
And you can check your my_new_app in your browser at:
http://localhost:8000/my_new_app
(Of course you can give any url to your my_new_app in your project's urls.py file.)
Now, you can create another app, in your Django project, called my_second_app and you should repeat the above steps for that app too. This way you will not have any problem importing views from different apps into urls.py files. This would be a very basic “good practice solution” for this problem in 2017 in Django 1.11.
The URLconfs documentation gives an example of the same situation
You can skip the imports and separate the urls by app as such:
urlpatterns = patterns('books.views',
(r'^/book/search/$', 'search'), #calls books.views.search
)
urlpatterns += patterns('contact.views', #make note of the '+='
(r'^/contact/search/$', 'search'), #calls contact.views.search
)
Heres the approach i took for different view/API versions:
from django.urls import path
from my_app import views as api_v1
from my_app import views_v2 as api_v2
urlpatterns = [
path('view_one', api_v1.ViewOne.as_view()),
path('view_two', api_v2.ViewTwo.as_view()),
]