I'm writing a program that enables my Django application to consume a REST API. My problem is that Django rejects the program if I run it as a .py file, but accepts it via shell. The program is divided into two files: one that interacts with the API, and another that interacts with Django. The main folder structure is as follows:
/root folder
[rest of Django project]
-__init__.py
-test.py
-mid_side.py
-teamup_api/
-__init__.py
-teamup.py
where test.py is the file that starts the program, mid_side.py is the Django-side part, and teamup.py is the API-side part. Below is the specific code I'm having trouble with.
test.py
import django
from mid_side import dates
from datetime import datetime
start = datetime(2017,7,28)
end = datetime(2017,8,19)
test = dates(start,end)
print(test)
Where dates is a method from mid_side that accepts two datetime objects as parameters.
According to Django, the problem emerges in mid_side.py, as it imports models from an app in the main Django project. The specific line Django has issues with is from events.models import Service, where events is an app Django uses and Services is a model. The traceback is
Traceback (most recent call last):
File "test.py", line 2, in <module>
from mid_side import dates
File "/home/brian/Github/nydkc11/nydkcd11/mid_side.py", line 3, in <module>
from events.models import Service
File "/home/brian/Github/nydkc11/nydkcd11/events/models.py", line 1, in <module>
from embed_video.fields import EmbedVideoField
File "/home/brian/anaconda3/envs/server/lib/python3.6/site-packages/embed_video/fields.py", line 6, in <module>
from .backends import detect_backend, UnknownIdException, \
File "/home/brian/anaconda3/envs/server/lib/python3.6/site-packages/embed_video/backends.py", line 17, in <module>
from .settings import EMBED_VIDEO_BACKENDS, EMBED_VIDEO_TIMEOUT, \
File "/home/brian/anaconda3/envs/server/lib/python3.6/site-packages/embed_video/settings.py", line 7, in <module>
'embed_video.backends.SoundCloudBackend',
File "/home/brian/anaconda3/envs/server/lib/python3.6/site-packages/django/conf/__init__.py", line 56, in __getattr__
self._setup(name)
File "/home/brian/anaconda3/envs/server/lib/python3.6/site-packages/django/conf/__init__.py", line 39, in _setup
% (desc, ENVIRONMENT_VARIABLE))
django.core.exceptions.ImproperlyConfigured: Requested setting EMBED_VIDEO_BACKENDS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
I know for a fact the traceback concerns an app my project uses, django-embed-video. What I don't understand is why Django is indicating it as a problem considering a) Service doesn't use fields from django-embed-video, b) I successfully deployed the application on my project earlier. My questions are thus as follows:
1) Why does this problem occur in the .py file and not in shell?
2) What is causing Django to output the traceback?
Below is relevant code from the program. Please notify me if additional clarifications are required. Thank you!
*I decided not to include teamup.py as this is more of a Django-side problem, but I will include it if requested.
mid_side.py
from dateutil.parser import parse
from events.models import Service
import datetime
from teamup_api.teamup import *
def dates(start,end):
event_list = day_query(start.year, start.month, start.day, end.year, end.month, end.day)['events']
service_objects = []
for event in event_list:
service_objects.append(Service(
title=event['title'],
school=none_parse(event['who']),
location=none_parse(event['location']),
start_time=parse(event['start_dt']),
end_time=parse(event['end_dt']),
all_day=event['all_day'],
description=none_parse(event['notes'])
))
return service_objects
models.py
class Service(models.Model):
title = models.CharField(max_length=100)
school = models.CharField(max_length=100)
location = models.CharField(max_length=100)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
all_day = models.BooleanField()
description = models.TextField()
def __str__(self):
return self.title
UPDATE: I've been running 'shell' through manage.py shell, and 'console' via natively running a python file (e.g. python [file].py)
My problem was probably that I was using Django resources in the native python environment. As Chris indicates in the comments, creating a custom manage.py command instead of a .py start file should suffice.
Related
I'm absolutely frustraded about the fact that I can't start my Python journey. I have a simple service which I use as a training with Python which is new for me.
I've downloaded PyCharm and as long as I had one file, everything was fine.
That I decided to to some structure and suddenly my project stopped working.
I have a structure like:
project/
project/employees
project/employees/__init__.py
project/employees/employees.py
project/server.py
project/venv/
project/venv/(...)
The project is a source root.
And yet I have something like this:
Traceback (most recent call last):
File "C:/Users/user/PycharmProjects/project/server.py", line 5, in <module>
from employees.employees import Employees, EmployeesName
File "C:\Users\user\PycharmProjects\project\employees\employees.py", line 4, in <module>
from server import db_connect
File "C:\Users\user\PycharmProjects\project\server.py", line 5, in <module>
from employees.employees import Employees, EmployeesName
ImportError: cannot import name 'Employees'
I tested this with VS Code and CMD and the same happend.
I would be grateful for any suggestions!
EDIT:
employees.py:
from flask_jsonpify import jsonify
from flask_restful import Resource
from server import db_connect
class Employees(Resource):
(...)
class EmployeesName(Resource):
(...)
The problem here is that you have a circular dependency.
In employees.py you import server.py; and vice versa.
You have to rearrange your .py files in order that not to happen anymore.
I want to execute a python file where I want to check if there are new rows in a csv file. If there are new rows, I want to add them to a database.
The project tree is as follows:
Thus, the file which I want to execute is check_relations.py inside relations folder.
check_relations.py is as follows:
from master.models import TraxioRelations
with open('AUTOI_Relaties.csv', 'rb') as tr:
traxio_relations = tr.readlines()
for line in traxio_relations:
number = line.split(';')[0]
number_exists = TraxioRelations.objects.filter(number=number)
print(number_exists)
The model TraxioRelations is inside models.py in master folder.
When I run python check_relations.py I get an error
Traceback (most recent call last):
File "check_relations.py", line 3, in <module>
from master.models import TraxioRelations
ImportError: No module named master.models
What am I doing wrong? How can I import model inside check_relations.py file?
i think the most usable way it is create commands
for example in your master catalog:
master /
management /
__init__.py
commands /
__init__.py
check_relations.py
in check_relations.py
from django.core.management.base import BaseCommand
from master.models import TraxioRelations
class Command(BaseCommand):
help = 'check_relations by file data'
def handle(self, *args, **options):
with open('AUTOI_Relaties.csv', 'rb') as tr:
traxio_relations = tr.readlines()
for line in traxio_relations:
number = line.split(';')[0]
number_exists = TraxioRelations.objects.filter(number=number)
print(number_exists)
! don't forget to change the path to the file AUTOI_Relaties.csv or put it to the new dir
and then you can run in shell:
./manage.py check_relations
When using Django, you are not supposed to run an individual module on its own. See eg https://docs.djangoproject.com/en/1.11/intro/tutorial01/#the-development-server.
I have a basic parser app I'm building in Python. I monitors a folder and imports files when they are dropped there. I have a MongoDB that I'm trying to save the imports to. There's almost nothing to it. The problem happens when I try to include one of my class/mongo-document files. I'm sure it's a simple syntax issue I don't understand. I have all my requirements installed, and I'm running this in an virtual env. This is my first python app though, so it's likely something I'm not seeing.
My file structure is
application.py
requirements.txt
__init__.py
-services
parser.py
__init__.py
-models
hl7message.py
__init__.py
Here is application.py
from mongoengine import connect
import os, os.path, time
from services import parser
db = connect('testdb')
dr = 'C:\\Imports\\Processed'
def processimports():
while True:
files = os.listdir(dr)
print(str(len(files)) + ' files found')
for f in files:
msg = open(dr + '\\' + f).read().replace('\n', '\r')
parser.parse_message(msg)
print('waiting')
time.sleep(10)
processimports()
requirements.txt
mongoengine
hl7
parser.py
import hl7
from models import hl7message
def parse_message(message):
m = hl7.parse(str(message))
h = hl7message()
hl7message.py
from utilities import common
from application import db
import mongoengine
class Hl7message(db.Document):
message_type = db.StringField(db_field="m_typ")
created = db.IntField(db_field="cr")
message = db.StringField(db_field="m")
If I don't include the hl7message class in the parser.py it runs fine, but as soon as I include it I get the error, so I'm sure it has something to do with that file. The error message though isn't to helpful. I don't know if I've got myself into some kind of include loop or something.
Sorry, stack trace is below
Traceback (most recent call last):
File "C:/OneDrive/Dev/3/Importer/application.py", line 3, in <module>
from services import parser
File "C:\OneDrive\Dev\3\Importer\services\parser.py", line 2, in <module>
from models import hl7message
File "C:\OneDrive\Dev\3\Importer\models\hl7message.py", line 2, in <module>
from application import db
File "C:\OneDrive\Dev\3\Importer\application.py", line 23, in <module>
processimports()
File "C:\OneDrive\Dev\3\Importer\application.py", line 17, in processimports
parser.parse_message(msg)
AttributeError: module 'services.parser' has no attribute 'parse_message'
This is a circular import issue. Application.py imports parser, which imports h17 which imports h17message, which imports application which runs processimports before the whole code of the parser module has been run.
It seems to me that service modules should not import application. You could create a new module common.py containing the line db = connect('testdb') and import db from common both in application.py and in h17message.
When i run the same code in django shell it works fine for me. but when I fire up the Python interpreter (Python 2) to check some things, I get the an error when I try importing - from django.contrib.auth.models import User
import os
import django
django.setup()
import smtplib
import sys
sys.path.insert(0, "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware")
import dateutil.relativedelta
from django.conf import settings
from django.contrib.auth.models import User
from opaque_keys.edx.keys import CourseKey
from courseware.models import StudentModule
from datetime import datetime
def PCSurvey_email():
for student in StudentModule.objects.filter(module_type="PCSurvey"):
two_months_date = datetime.now().date() - dateutil.relativedelta.relativedelta(months=2)
created = student.created.date()
if created == two_months_date :
user_id = student.student_id
user_email = User.objects.get(id = user_id).email
FROM = "user#example.com"
TO = [user_email] # must be a list
SUBJECT = "Hello!"
TEXT = "This message was sent with Python's smtplib."
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP('outlook.net')
server.sendmail(FROM, TO, message)
server.quit()
#deleting the module
smod = StudentModule.objects.get(module_type="PCSurvey", course_id = student.course_id, student_id= student.student_id)
smod.delete()
The error that I get is
Traceback (most recent call last):
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/PCSurvey_email.py", line 4, in <module>
django.setup()
File "/usr/local/lib/python2.7/dist-packages/django/__init__.py", line 22, in setup
configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
File "/usr/local/lib/python2.7/dist-packages/django/conf/__init__.py", line 53, in __getattr__
self._setup(name)
File "/usr/local/lib/python2.7/dist-packages/django/conf/__init__.py", line 39, in _setup
% (desc, ENVIRONMENT_VARIABLE))
django.core.exceptions.ImproperlyConfigured: Requested setting LOGGING_CONFIG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
Any help on this is very much appreciated.
Django needs to be setup, in order to run fine, when you run it through manage.py shell, manage.py takes care or setting it up for you, but doing it via a python script, needs manual setup.
You also seem to have used your defined models, to be able to import them into your python script, you need to add the path to the root folder of your project to the current python path.
Finally, you need to tell django where your settings file is (before setting up your django), in your manage.py file, you should have something like this :
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")
Go make it a constant, name it * DEFAULT_SETTINGS_MODULE *, so you now have:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", DEFAULT_SETTINGS_MODULE)
Now you need to import the constant into your script and tell django (By setting an env var) where it should look for the settings file.
So in all:
import sys, os
sys.path.insert(0, "/path/to/parent/of/courseware") # /home/projects/my-djproj
from manage import DEFAULT_SETTINGS_MODULE
os.environ.setdefault("DJANGO_SETTINGS_MODULE", DEFAULT_SETTINGS_MODULE)
import django
django.setup()
This way you're setup up just fine.
For new users coming on this question.
If you don't want to setup django settings file manually as described wonderfully by #SpiXel
You can run python manage.py shell from the project directory which will basically link the settings file that django needs automatically.
When you open a shell, django automatically sets itself up.
With Python interpreter you have to do this manually:
import django
django.setup()
Just a simple solution all can try!
I tried to run my custom script inside shell only by using the following way:
python manage.py shell < /path_to_script
I've had a similar problem to this one before where I received a nearly identical error message, i.e.
C:\Users\David J\optilab\optilab_project>python functional_tests.py
Traceback (most recent call last):
File "functional_tests.py", line 4, in <module>
from optilab.models import Design
File "C:\Users\David J\optilab\optilab_project\optilab\models.py", line 10, in <module>
class Design(models.Model):
File "C:\Users\David J\optilab\optilab_project\optilab\models.py", line 11, in Design
name = models.CharField(max_length=30)
File "C:\Python27\lib\site-packages\django\db\models\fields\__init__.py", line 1072, in __init__
super(CharField, self).__init__(*args, **kwargs)
File "C:\Python27\lib\site-packages\django\db\models\fields\__init__.py", line 166, in __init__
self.db_tablespace = db_tablespace or settings.DEFAULT_INDEX_TABLESPACE
File "C:\Python27\lib\site-packages\django\conf\__init__.py", line 55, in __getattr__
self._setup(name)
File "C:\Python27\lib\site-packages\django\conf\__init__.py", line 41, in _setup
% (desc, ENVIRONMENT_VARIABLE))
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
But it was being produced because I was calling my test incorrectly from the shell. Now I am attempting to run a functional test, which I have done several times before successfully using the command
"python functional_tests.py"
in my project folder -- but it produces the above error message. Can anyone tell me what I'm doing wrong, or why this may have worked before but not now? thank.
Edit:
Here is functional_tests.py:
from selenium import webdriver
import unittest
from selenium.webdriver.common.keys import Keys
from optilab.models import Design
from automa.api import *
class HomeTest(unittest.TestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.get('http://localhost:8000/lab')
self.new_design = self.browser.find_element_by_id("new_design")
self.load_design = self.browser.find_element_by_id("load_test")
self.design_name = self.browser.find_element_by_id("design_name")
self.browser.implicitly_wait(3)
def test_latest_designs_displayed_in_table(self):
#
self.browser.implicitly_wait(3)
self.design_table = self.browser.find_element_by_id("design_table")
self.rows = self.browser.find_elements_by_tag_name('tr')
self.assertTrue(
any(row.text == 'My First Design' for row in rows),
"New design did not appear in test table."
)
def test_entering_text_activates_new(self):
# user enters name of design. new becomes clickable.
self.browser.implicitly_wait(3)
self.design_name.send_keys("sample_design")
def test_new_test_can_be_saved_and_retrieved(self):
name = "sample design"
self.design_name.send_keys(name)
self.new_design.click()
self.browser.implicitly_wait(3)
self.saved_design = Design.objects.get(name=design_name)
def test_entering_name_of_previously_saved_test_activates_load(self):
# user enters the name of a previously saved test. load button becomes clickable.
design = Design(name="sample_design")
saved_design = Design.objects.get(id=1).name
self.browser.implicitly_wait(3)
self.design_name.send_keys(saved_design)
self.load_design.click()
def test_entering_name_of_previously_saved_test_but_clicking_new_prompts_overwrite(self):
# user entes name of saved test but clicks new. dialogue box asks if test should be overwritten.
previously_saved_design = Design.objects.get(id=1).name
self.design_name.send_keys(previously_saved_design)
def test_clicking_save_redirects_to_model(self):
pass
def tearDown(self):
self.browser.quit()
if __name__ == '__main__':
unittest.main()
The start of your script should look something like this
import os, sys
sys.path.append(os.getcwd())
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "optilab.settings") # or whatever
import django
django.setup()
from selenium import webdriver
import unittest
from selenium.webdriver.common.keys import Keys
from optilab.models import Design
from automa.api import * # try not to do this
This happens because Django has not been correctly setup before trying to call settings, it has no way to know which project settings should be used without the "DJANGO_SETTINGS_MODULE" variable and the django.setup() call is essential to import models and access the database. (see e4c5's answer for that method)
However, this is not the recommended method or the easiest one. You can call the functional tests just like the unit tests from manage.py test and Django will automagically setup everything for you, it'll even use a tempdb for functional tests. If your functional tests include insertions and updates in the functional tests (and you should) a tempdb comes in handy.
To use this facility though, you must change a few things in your code.
First there is the matter of the filename, the default pattern for manage.py test(doc) is "test*.py", you can change this with -p or --pattern but the usual solution is to rename functional_tests.py to tests.py and place it inside a functional_tests folder. That way you can call just the functional tests by calling manage.py test functional_tests.
Also, instead of importing TestCase from unittest you should look into using TestCase(doc) from django.test or even LiveServerTestCase(doc) which would save you the trouble of running manage.py runserver yourself.