I separate my views into some files.
so say I have this:
website/
│ manage.py
│
├───app
│ │ admin.py
│ │ admin.pyc
│ │ models.py
│ │ models.pyc
│ │ tests.py
│ │ views.py
│ │ views.pyc
│ │ views_home.py
│ │ views_home.pyc
│ │ __init__.py
│ │ __init__.pyc
│ │
│ └───templates
│
├───locale
│
│
└───website
settings.py
settings.pyc
urls.py
urls.pyc
wsgi.py
wsgi.pyc
__init__.py
__init__.pyc
In my urls.py I import each views file. I write:
url(r'^home/$', views_home.home),
One thing to mention, I also import all the views from views.py to other views files, means in views_home.py I do
from views import *
Because I want some functions which are in my views.py to be available.
I have a lot of imports in the views file, some of them are django different HttpResponse type objects (Http404, HttpResponse, render etc.)
+ more external libraries.
The point is- if I will turn my views into a modules - I will create a views folder with __init__.py file and store my views file in this folder. How can I avoid import the same objects which are needed in every views file (like HttpResponse), in each view file in the package?
Can I write an import in __init__.py file that will be imported for all the files in the package? (like say, HttpResponse)
I usually see the __init__.py file is empty, what use does it have beside telling python that the folder is a package?
You cannot - and should not try to - "avoid" this; it is a fundamental principle in Python that all names used in a module are defined there or imported explicitly.
Related
I have a Project where there is a python(.py) file inside a Directory say A, under the folder A , I have a file having the code:
from utils.utils import csv_file_transform
where utils is a sibling directory to A
/A
file.py
/utils
__init__.py
utils.py
but, I am getting a error No Module named utils.utils, utils is not a package
I tried adding the path using sys, but its still giving the same error
import sys
sys.path.append('C:/Users/Sri/Documents/newmod/folder/utils')
The code is working fine in ubuntu but not in windows, I am using a windows system
as much as I don't support link only / reference only answers I reckon that your question is answered best by referencing the existing discussions and providing broader context on Python importing mechanism.
Your Requirements
Are you actually working on creating on Python module? If this is the case, it would be good if you could establish a rigorous structure for your module and follow those guidelines.
Consider the following article by Jason C. McDonald on strutting a hypothetical module omission in Python. Given the following structure:
omission-git
├── LICENSE.md
├── omission
│ ├── app.py
│ ├── common
│ │ ├── classproperty.py
│ │ ├── constants.py
│ │ ├── game_enums.py
│ │ └── __init__.py
│ ├── data
│ │ ├── data_loader.py
│ │ ├── game_round_settings.py
│ │ ├── __init__.py
│ │ ├── scoreboard.py
│ │ └── settings.py
│ ├── game
│ │ ├── content_loader.py
│ │ ├── game_item.py
│ │ ├── game_round.py
│ │ ├── __init__.py
│ │ └── timer.py
│ ├── __init__.py
│ ├── __main__.py
│ ├── resources
│ └── tests
│ ├── __init__.py
│ ├── test_game_item.py
│ ├── test_game_round_settings.py
│ ├── test_scoreboard.py
│ ├── test_settings.py
│ ├── test_test.py
│ └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
Jason would import the modules in a following manner from omission.common.game_enums import GameMode.
Relative Imports
#am5 suggests adding
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))
to your __init__.py files. If you study the related discussion you will observer that views on modifying sys.path are diverse. Some may argue that failed imports and errors like:
ImportError: attempted relative import with no known parent package
are actually indication of code smell. As a solution, which I hope you won't find patronising, I would suggest that you solve your importing challenge by:
a) Deciding on your requirements on how "deep" you want to go into modular architecture.
b) Adopting a corresponding recommended architecture with rigorous approach to module structure
c) Refraining from hard-coding any path via sys.path. Appending relative paths, as outlined above, is not a flawless solution but has some merits and may be worth considering.
Other worthy discussions/artefacts
Best structure for the Python project
Sample project by PyPa (GitHub)
Importing files from different folders
I know this question has come up but many answers refer to older versions of Django and Python. I am running Django 3 and Python 3.
Besides in our project we have decided to separate each model in its own file under a "models" folder. Please see below our tree structure:
├── db.sqlite3
├── manage.py
├── poi
│ ├── admin.py
│ ├── apps.py
│ ├── CHANGELOG.md
│ ├── fabfile.py
│ ├── __init__.py
│ ├── LICENSE
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20210104_1048.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-38.pyc
│ │ ├── 0002_auto_20210104_1048.cpython-38.pyc
│ │ └── __init__.cpython-38.pyc
│ ├── models
│ │ ├── __init__.py
│ │ ├── layer.py
│ │ ├── poi.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-38.pyc
│ │ │ ├── layer.cpython-38.pyc
│ │ │ ├── poi.cpython-38.pyc
│ │ │ └── tag.cpython-38.pyc
│ │ └── tag.py
│ ├── models.py
In our models/init.py we have:
from .poi import Poi
from .tag import Tag
from .layer import Layer
In our models/poi/poi.py we have:
from django.db import models
from .tag import Tag
from .layer import Layer
class Poi(models.Model):
...
...
tags = models.ManyToManyField('Tag', through='Layer')
def __str__(self):
return self.name
In our models/poi/tag.py we have:
from django.db import models
import poi.models.poi
import poi.models.layer
class Tag(models.Model):
name = models.CharField(max_length=100)
pois = models.ManyToManyField('Poi', through='Layer')
def __str__(self):
return self.name
In our models/poi/layer.py we have:
from django.db import models
import poi.models.poi
import poi.models.tag
class Layer(models.Model):
poi = models.ForeignKey(Poi, on_delete=models.CASCADE)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
The error comes up when we run python3 manage.py makemigrations.
Error:
File "/media/elena/DATA2/Python-projects/osm-pois/osm-pois/upoi/poi/models/layer.py", line 8, in Layer
poi = models.ForeignKey(Poi, on_delete=models.CASCADE)
NameError: name 'Poi' is not defined
We have tried other ways of import in layer.py such as:
from .poi import Poi
from .tag import Tag
But that gave us the following error:
File "/media/elena/DATA2/Python-projects/osm-pois/osm-pois/upoi/poi/models/layer.py", line 2, in <module>
from .poi import Poi
ImportError: cannot import name 'Poi' from partially initialized module 'poi.models.poi' (most likely due to a circular import) (/media/elena/DATA2/Python-projects/osm-pois/osm-pois/upoi/poi/models/poi.py)
Any idea of how to solve this? Thanks!
I am posting as an answer what #TonySuffolk66 suggested via a comment since it worked perfectly. Thanks again!
Because your models are defined in different files, try doing this : poi = models.ForeignKey('Poi', on_delete=models.CASCADE) That is using a string for the model name, not a reference name. You can't 'easily' import other models like this due to the way that Django initializes
I want to run my stand-alone script csvImp.py, which interacts with the database used by my Django site BilliClub. I'm running the script from the project root (~/BilliClub) on my virtual environment django2.
I've followed the instructions here but for DJANGO_SETTINGS_MODULE rather than the secret key. The part that trips me up is what value to assign to the environmental variable. Every iteration I've tried has yielded an error like ModuleNotFoundError: No module named 'BilliClub' after running
(django2) 04:02 ~/BilliClub $ python ./pigs/csvImp.py.
I am reloading the shell every time I try to change the variable in .env so the postactivate script runs each time and I'm making sure to re-enter my virtualenv. The problem just seems to be my inability to figure out how to path to the settings module.
The .env file:
# /home/username/BilliClub/.env #
DJANGO_SETTINGS_MODULE="[what goes here???]"
Full path of my settings.py is /home/username/BilliClub/BilliClub/settings.py.
Abridged results from running tree:
(django2) 04:33 ~ $ tree
.
├── BilliClub
│ ├── BilliClub
│ │ ├── __init__.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── manage.py
│ ├── media
│ ├── pigs
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── bc2019.csv
│ │ ├── csvImp.py
│ │ ├── models.py
│ │ ├── models.pyc
│ │ ├── tests.py
│ │ ├── urls.py
│ │ └── views.py
│ └── ...
It looks like you should make csvImp a custom management command and then
DJANGO_SETTINGS_MODULE is "BilliClub.settings" When you write your utility function as Django Management Command you get all the Django configuration for free, and the root directory of your command is the same as the root directory of the web app, and its the directory where manage.py is.
Take a look at https://docs.djangoproject.com/en/3.1/howto/custom-management-commands/
I have an existing project (let's name it main) on Django and several applications in it. There is a separate project, also in django, and one application inside it (we will call this the second one). Here is a generalized file structure for project "second":
my_second_project
│ manage.py
│ models.py
│ my_models.py
│ my_views.py
│
├───myapp
│ │ admin.py
│ │ apps.py
│ │ Funcs.py
│ │ models.py
│ │ tests.py
│ │ urls.py <-- from here urls import to project urls file
│ │ views.py
│ │ __init__.py
│ │
│ ├───migrations
│ │ └───...│
├───my_second_project
│ │ asgi.py
│ │ settings.py
│ │ urls.py <-- HERE all urls i need
│ │ wsgi.py
│ │ __init__.py
├───templates
│ ...
│
└───__pycache__
models.cpython-37.pyc
Here is a generalized file structure for project "main":
main_project
├───app ...
│ ├───...
├───main_project
│ ├───media
│ │ └───user_uploads
│ ├───settings
│ │ └───base.py
│ └───urls.py
├───app ...
│ ├───...
├───app ...
│ ├───...
└───static
├...
I need to integrate "second" project into my existing one (main project), ideally without making any changes to the second project. I tried to do it in the same way that applications are integrated (via urls include), but it seems that it does not work with projects because django writes "myapp module not found".
url('data-classifier/', include('my_second_project.my_second_project.urls'))
Is there some way to add a "second" project to my "main" project without changing the "second" one?
When you deploy these projects they won't be stored in directories nearby. Ideally they won't be on the same server at all.
Instead if you can't afford to copy (or move) contents of the app you need from second to main project, and you don't want to redirect with nginx, make a small app in your main project and from urls.py redirect to endpoints of second.
main_project.my_second_project.urls.py
from django.urls import path
from django.views.generic import RedirectView
app_name = 'my_second_project'
urlpatterns = [
path('endpoint/', RedirectView.as_view(url='<my_second_project_url>'), name='endpoint')
]
If you're running main locally at 8000, and second at 8001, then you'd put 'http://localhost:8001/endpoint/' as url up there.
I have a directory that looks like this:
├── libraryweb
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── __pycache__
│ │ ├── __init__.cpython-37.pyc
│ │ ├── forms.cpython-37.pyc
│ │ ├── models.cpython-37.pyc
│ │ └── routes.cpython-37.pyc
│ ├── forms.py
│ ├── models.py
│ ├── routes.py
│ ├── save_books.py
│ ├── site.db
│ ├── static
│ │ ├── book_pics
│ │ └── user_pics
│ │ └── default.jpg
│ └── templates
│ ├── account.html
│ ├── base.html
│ ├── book.html
│ ├── book_update.html
│ ├── home.html
│ ├── login.html
│ └── register.html
└── run.py
Now in the file save_books.py, I want to import a class Book from models.py in the libraryweb module. I have tried from libraryweb.models import Book, from .models import Book, and from models import Book, but none of them works.
The __init__.py file contains the following code:
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view='login'
login_manager.login_message_category='info'
from libraryweb import routes
I got the following error message:
Exception has occurred: ModuleNotFoundError
No module named 'libraryweb'
File "/Users/gracezhou/cs/python_flask/flask-library/hey/libraryweb/save_books.py", line 3, in <module>
from libraryweb.models import Book
Have you set your PYTHONPATH variable pointing to your application path ?
Can you please show your ouput of below command.
import sys
sys.path
All directories where module files are exist needed to be in PYTHONPATH env variable. If you dump everything in the single directory then you just need folder which contains python files into your PYTHONPATH. Refer to below https://docs.python.org/3/library/sys.html#sys.path