Same functions in different views - Django - django

I have started learning Django recently and am following the code examples given in the tutorial of the Django site. Accordingly, I have created a site 'mysite' and an app 'books' in that site. Consequently, there are two 'views.py' files in the resultant directory structure - one in the 'mysite' folder and one in 'books' folder and there's only one 'urls.py' file - in the 'mysite' folder only. My question is the following - how do I avoid name conflicts for the functions that I create in the two 'views.py' files? If there are two functions with the same name in both the files, how does Django resolve which function to call for a given URL pattern in 'urls.py' file?
The following is my directory structure:
C:.
│ manage.py
│
├───books
│ admin.py
│ admin.pyc
│ models.py
│ models.pyc
│ tests.py
│ views.py
│ views.pyc
│ __init__.py
│ __init__.pyc
│
└───mysite
base.html
base_blog.html
base_welcome.html
currdate.html
settings.py
settings.pyc
urls.py
urls.pyc
views.py
views.pyc
wsgi.py
wsgi.pyc
__init__.py
__init__.pyc
An additional and related question - if I have multiple projects (like 'mysite') and different apps in those projects, how do I differentiate the URLs across the projects? I mean, currently, the URL http://127.0.0.1:8000/hello is mapped to a view function in 'mysite' project. What if I now have one more project, say 'mynewsite', how would Django resolve the URL http://127.0.0.1:8000/hello to the view function of 'mynewsite'? I hope my question is clear.
Thanks,
Rakesh.

In python you can import libraries (in this case file like views.py) one of them would be causing name conflicts you are talking about, namely
from books.views import my_view
from mysite.views import my_view
in that case, my_view will simply be overwritten. However, you can also do the following
import books.views
import mysite.views
In that case, to access the imported view, you will have to use full path, i. e. books.views.my_view, therefore there is no name conflict.
As for your other question, consider the following urls.py contents:
urlpatterns = patterns('',
url(r'^$', mysite.views.my_view, name='index'),
You can replace it with
urlpatterns = patterns('',
url(r'^$', books.views.my_view, name='index'),

Related

How to create hierarchical urls within django app?

I have multiple app based django project and within some apps url scheme getting complicated due to number of models. Hence I'm looking a way to make a hierarchical url structure within the app.
In my project's urls file I do the following.
from order import urls as order_urls
In the order app I have urls.py and urls directory which contains separate url patterns for each model as follows.
In the app's urls.py file I import the model's urls as follows.
from urls import rental as rental_urls
urlpatterns = [
url(r'^rental-request/', include(rental_urls)),
]
This gives me the error: ModuleNotFoundError: No module named 'urls'
If I put __init__.py it gives me circular import error.
I'm not sure this is the correct way/possible for my requirement. Anyone could explain the correct way to achieve it?
Having a folder called urls (with an __init__.py file) as well as a file urls.py in the same folder will probably cause trouble to load the module order.urls from anywhere in your project. How does Python will know which file must be loaded ?
Consider this structure:
├── main.py
├── urls
│   └── __init__.py
└── urls.py
And this content for each file:
# urls/__init__.py
urlpatterns = "I'm in folder"
# urls.py
urlpatterns = "I'm in file"
# main.py
import urls
print(urls.urlpatterns)
When you run main.py, the result is:
% python main.py
I'm in folder
Possible solutions :
You may delete the urls.py and move its content to urls/__init__.py, or rename the folder urls to avoid conflicts and updates imports accordingly (in urls.py)

Overriding/Adding to Django URLs in settings rather than urls

It seems that the latest Django debug toolbar module has changed to middleware now and requires explicit URL setup to work. With my Django projects I always try to keep settings organised based on environment and not have if settings.DEBUG littered all over the settings files and project.
My settings layout is a general:
common.py (everything in here)
development.py (dev only things here)
production.py (prod only things here)
Is there a way in Django 1.10 I can add to the URLs in the development.py file so that I can keep away from if settings.DEBUG. Or will we be forced to use this method if wanting to use the new version of the debug toolbar?
I just find the below a bit of an anti-pattern
if settings.DEBUG:
import debug_toolbar
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]
If you do not feel like testing for the value of settings.DEBUG in your URL configuration, you may manage your URLs with a pattern similar to the one you are using for your settings.
Instead of a urls.py file, you would have a urls package with this structure:
urls
├── __init__.py
├── common.py
├── local.py
└── production.py
In your different settings files you would specify which URL conf file to use this way:
# settings/local.py
ROOT_URLCONF = 'urls.local'
 
# settings/production.py
ROOT_URLCONF = 'urls.production'
The urls/common.py file will expose a urlpattern member containing all the URL patterns common to all configurations which you will import and use in urls/local.py and urls/production.py.
For example:
# urls/common.py
urlpatterns = [
# Put all common URL patterns here
]
 
# urls/local.py
from .common.py import urlpatterns as common_urlpatterns
urlpatterns = common_urlpatterns + [
url(r'^__debug__/', include(debug_toolbar.urls)),
]
If you want my opinion, this solution feels like overkill given that, as opposed to settings, URL configurations should not differ much between environments.

Django REST Framework: How to add prefix in URL for versioning

I am trying to create version for REST application. Here is my URL Examle
www.myapi.com/foo [default version]
www.myapi.com/v1/foo [version one]
This is the project structure
├── __init__.py
├── settings.py
├── urls.py
├── default_app
│ ├── __init__.py
│ ├── serializer.py
│ ├── models.py
│ ├── views.py
│ ├── urls.py
│
└── v1_app
├── __init__.py
├── serializer.py
├── models.py
├── views.py
├── urls.py
default_app urls.py
from django.conf.urls import *
from default_app import views as df_views
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'foo', df_views.viewname, "foo")
urlpatterns = router.urls
v1_app urls.py
from django.conf.urls import *
from v1_app import views as ver_views
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'foo', ver_views.viewname, "foo")
urlpatterns = router.urls
main file for urls.py
from django.conf.urls import patterns, include, url
from defualt_app import urls as default_urls
from v1_app import urls as v1_urls
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += patterns('',
url(r'^', include(default_urls, namespace="default")),
url(r'^v1/', include(v1_urls, namespace="v1"))
)
urlpatterns += staticfiles_urlpatterns()
My issue is, when i using simple url without any prefix then it is working
www.myapi.com/foo
and when i used version prefix v1 or v2 then it throws error [Page not found (404)]
www.myapi.com/v1/foo
I got this idea from this link
https://stackoverflow.com/a/21839842/1558544
If I don't use middleware class then is this possible to get same result?
Thank you
Django REST Framework does not support url namespaces well, but there are solutions to making them work for most cases.
In the case of serializers, you must define all fields that are hyperlinked with a HyperlinkedRelatedField, including the url field that is automatically added, which is a HyperlinkedIdentityField. This includes setting the view_name argument on all of the fields to the correct, automatically generated view name. This should be something like [namespace]:[base_name]-detail.
But this also means you cannot use the DefaultRouter index page that is generated by the DefaultRouter, as it does not handle namespaces at all. In order to get one, you are going to need to either create your own, or override the automatically generated view in the router.

ImportError After Moving App to Nested Folder

My application was working fine when I wanted to see whether I could organize my project in a better way. I read through this tutorial on structuring a django project.
Before my project structure was as follows:
camucamu
books
admin.py
models.py
views.py
__init__.py
static
templates
urls.py
views.py
settings.py
wsgi.py
__init__.py
What I wanted to do was move the books app into an apps folder. Thus I did that and changed the project structure to the following:
camucamu
apps
books
admin.py
models.py
views.py
__init__.py
static
templates
urls.py
views.py
settings.py
wsgi.py
__init__.py
I then changed the imports in views.py and admin.py
from books.models to apps.books.models.
I also changed INSTALLED_APPS in settings.py from books to apps.books.
When I then tried to run syncdb, I get the following error:
raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
django.core.exceptions.ImproperlyConfigured: ImportError apps.books: No module named apps.books
What am I messing up here so it can't find my app anymore?
Your apps folder does not have an __init__.py file so it cannot be recognized as a python module
I got the same error, following the same guide, as the last point of the following list was not cited. Make sure you performed the following changes:
Create a blank __init__.py file inside the apps folder (needed for python to recognize it as a package)
Update the import statements wherever you refer to an external app:
from projectname.apps.appname.models import YourModel, YourOtherModel
Inside settings.py edit INSTALLED_APPS such that it looks like this:
INSTALLED_APPS = (
...
# apps
'projectname.apps.appname1',
'projectname.apps.appname2',
)
This one is not specified in the guide: In all your urls.py files, update the urlpatterns!
BEFORE:
# client views
urlpatterns += patterns('appname',
...
)
AFTER:
# client views
urlpatterns += patterns('projectname.apps.appname',
...
)
Finally remember to update your changes by calling python manage.py syncdb
Hope that helped.

Moving django apps into subfolder and url.py error

I have a question about putting django apps into "apps" subdirectory. I have the app called “faktura” in a project_root. I didn’t like the fact it lies there and I want to store all my apps under “apps” subdirectory.
So, I found out that I could extend python path to “apps” subdir, so after looking in the internet, I added this string to settings.py: sys.path.insert(0, os.path.join(PROJECT_PATH, "apps")). Then I added the app to INSTALLED_APPS like “faktura”. Everything worked smooth until I added url(r'^faktura/', include('faktura.urls')) to urls.py in the root. Since that, Django throws the error message “No module named faktura” full taceback is here: http://dpaste.com/737380/
What can be wrong here, why only urls.py can’t find the app? And does it can’t find this app if I added it to the PATH? I spent a morning trying to figure out what’s wrong and now I need your help.
I don't know why the previous answer got -1 aside from maybe a few redundant lines that can be corrected. Anyway, I found a slightly different method that doesn't involve adding anything to the python path.
This is my final directory structure, I will explain in a moment:
mysite
├── mysite
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── apps
│ ├── __init__.py
│ └── myfirstapp
│ ├── __init__.py
│ ├── admin.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
No matter if you have just created your project or if you want to move your apps, create the apps subdirectory that should contain your apps. The trick is to add an __init__.py to that directory.
mkdir apps
touch apps/__init__.py
Now you can move your existing apps into the apps subdirectory. If you would like to create a new one instead here are the commands:
python manage.py mysecondapp
mv mysecondapp apps/
Warning: Don't be tempted to call python manage.py ./apps/mysecondapp. For some reason this deletes all other apps in that directory. I just lost a day of work this way.
Next, you will need to fix a few imports. Your settings.py should be prefixed with apps:
INSTALLED_APPS = (
...
'apps.myfirstapp',
'apps.mysecondapp'
)
Lastly, fix your project's urls.py to prefix apps:
urlpatterns = patterns('',
url(r'^myfirstapp', include('apps.myfirstapp.urls')),
...
)
Depending on how you wrote them, you might also have to fix a few imports inside your app. Either just use from models import MyFirstModel or also prefix it using from apps.myfirstapp.models import MyFirstModel.
In short, if you make your apps directory a python package (by adding __init__.py), you can use it as part of the import path. This should work regardless of the deployment method with no extra configuration.
Use BASE_DIR variable from the settings.py. It should be already defined:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Better not use the __file__ attribute in manage.py and wsgi.py, as they are located in different directories.
So, just add the following to manage.py and wsgi.py (and to the celery.py if you use Celery):
from django.conf import settings
sys.path.append(os.path.join(settings.BASE_DIR, "apps"))
You will end up with the following project structure:
project
├── project
│ ├── __init__.py
│ ├── celery.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── apps
│ ├── app1
│ └── app2
└── manage.py
To keep your Django applications in a subfolder (such as apps/), first add the following to your settings.py:
import os
PROJECT_ROOT = os.path.dirname(__file__)
Then in manage.py:
Right under #!/usr/bin/env python add:
import sys
from os.path import abspath, dirname, join
from site import addsitedir
Right before if __name__ == "__main__" : add:
sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))
#Radu Gheorghiu's answer; It is not necessary to edit settings.py, and the insert path line can be condensed to 1 line of code.
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "apps"))
I sourced this answer from http://obroll.com/nested-application-inside-apps-sub-folder-in-django-1-3/