I'm going through the Django tutorial and wanted to try out database manipulating with a python script but encounter a problem
My script:
from polls.models import Question, Choice
from django.utils import timezone
import numpy as np
#Questions
nquestions=3
q=np.empty([nquestions, 10], dtype=object)
qtext=q
qtext[0]="What's up?"
qtext[1]="What's new?"
qtext[2]="What's old?"
#Choices
q[0,1]="Not much"
q[0,2]="The sky"
q[1,1]="This question"
q[1,2]="This answer"
q[2,1]="No more originality"
q[2,2]="xxxxxxx"
#Check if exists and apply
for i in range(0, len(q)):
q[i,0]=Question(question_text=qtext[i], pub_date=timezone.now())
if Question.objects.filter(question_text=qtext[i]).exists():
pass
else:
q[i,0].question_text=qtext[i]
q[i,0].save()
alen=len(q[i][q[i] != np.array(None)])
for ii in range(0, alen-1):
q[i,0].choice_set.create(choice_text=q[i,ii+1], votes=0)
I get the error django.core.exceptions.appregistrynotready apps aren't loaded yet. I'm running the script from terminal and it's places in the folder that contains the polls-folder (One level over modules.py, which I'm trying to import).
Writing the contents of my script works if i first run in terminal : python manage.py shell. Is there a way for me to run a script to manipulate the database through Djangos API, or do I have to enter information manually or send requests thŕough post?
You need to set the DJANGO_SETTINGS_MODULE environment variable and call django.setup() before you can import your models.
import os
import django
# Change mysite if your project has a different name
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
django.setup()
from polls.models import Question, Choice
...
See the docs for more info.
Another option is to write a custom management command. When you use manage.py to run your management command you don't have to set DJANGO_SETTINGS_MODULE or call django.setup().
Related
To run my Django's tests, I was using the manage.py file.
But I decided to create my own file runtests.py.
As specified in the Django's doc, the manage.py file will execute all methods whose name is starting like "test" and whose class inherits TestCase !
My aim is to use this searching method to display all possible tests (not running them).
So do you know where I could get this "searching method" ?
Thank you !
What you're looking for is called "test discovery", and you don't need to do it manually.
If you want to write a standalone script that runs your tests, you can simply invoke Django's test runner manually from Python code after configuring. The process for this is:
# First you need settings.
# You can do this by setting DJANGO_SETTINGS_MODULE:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'path.to.your.settings')
# Or you can do it manually:
SETTINGS_DICT = {
# Put all the settings you'll need in here...
}
from django.conf import settings
settings.configure(**SETTINGS_DICT)
import django
django.setup()
import sys
# Now you can run tests:
from django.test.utils import get_runner
TestRunner = get_runner(settings)
test_runner = TestRunner(verbosity=2, interactive=True)
failures = test_runner.run_tests(
['test_module_to_look_in']
)
sys.exit(bool(failures))
My project structure is as follows:
my_proj
---calculation
---cardata
---master
---my_proj
--- __init.py__
--- admin.py
--- settings.py
--- url.py
--- update_db_from_ftp.py ///// This is my custom file
In update_db_from_ftp.py I want to download an csv file from ftp and update the database(if necessary) once every day with cron.
But the problem is that I can't import model which I want to update. The model which I want to update is inside master folder in models.py file.
I try to import model as follows:
from master.models import ModelName
But I'm getting an error as follows:
Traceback (most recent call last):
File "update_db_from_ftp.py", line 6, in <module>
from master.models import ModelName
ImportError: No module named master.models
But I use the same model in cardata and calculation folder and I import it the same way as I try in update_db_from_ftp.py file, but there it works without problems.
Any idea how to solve it?
UDPATE
The structure of the master folder is as follows:
For using django code in an arbitrary external script, two things are needed:
Django should be setup (exactly what happens when you run django shell).
The root project should be in python path (not the inner folder with same name).
Here is sample code which will work irrespective of the location of the script (although if the script is not one-off, better to add it as management command):
import django
import os
import sys
sys.path.append("/path/to/my-proj/")
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my-proj.settings')
django.setup()
from master.models import ModelName
if __name__ == "__main__":
print(ModelName.objects.all())
I have this python file tasks.py
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DjangoWebProject.settings')
from django.contrib.auth.models import User
from logreg.models import ActivationCode
import datetime
def remove_users():
print 'hello worldddddddddddddddddddddddddddddddddd'
inactive_users = []
activation_codes = ActivationCode.objects.all()
for activation_code in activation_codes:
if datetime.datetime.date(activation_code.key_expires) < datetime.datetime.date(datetime.datetime.now()):
inactive_users.append(activation_code.user_id)
for inactive_user in inactive_users:
User.objects.filter(id=inactive_user).delete()
But this is in the root folder and when i try to execute it, it gives me the following error
File
"C:\Users\deybala1\AppData\Local\Continuum\Anaconda2\lib\site-packages\dj
ango\apps\registry.py", line 124, in check_apps_ready
raise AppRegistryNotReady("Apps aren't loaded yet.") django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
How do i fix this?
If you're creating any script that is using your django project, it is absolutely necessary to set path to settings of your project before any import from django or your project. And you're importing user model from django in 1st line and model from your project in second.
Also, you will need to call django.setup() first.
To fix that, move import os and setting path to django settings to the very beginning of your script, and put django.setup() just after that (with proper import), like this:
# first, set path to project settings
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DjangoWebProject.settings')
import django
django.setup()
# now you can import anything else
from django.contrib.auth.models import User
from logreg.models import ActivationCode
import datetime
def remove_users():
print 'hello worldddddddddddddddddddddddddddddddddd'
inactive_users = []
activation_codes = ActivationCode.objects.all()
for activation_code in activation_codes:
if datetime.datetime.date(activation_code.key_expires) < datetime.datetime.date(datetime.datetime.now()):
inactive_users.append(activation_code.user_id)
for inactive_user in inactive_users:
User.objects.filter(id=inactive_user).delete()
Note that you're trying to add a settings module inside a script that already requires it.
Wouldn't it be easier if you add a specific django command? Thanks to it you'd be able to start your task with python manage.py --settings=<path_to_your_settings>.
Another tip:
Move every django import statement below
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DjangoWebProject.settings')
I have this folder structure for django
settings/dev.py
settings/prod.py
settings/test.py
Then i have common settings in settings/common.py in which i check the ENV variable like
if PROD:
from settings.prod import *
Based on ENV variable each one of them will be active
I want to use something like this in my code
from myapp import settings
rather than
from myapp.settings import dev
This is the method which I follow. Learnt this from the book Two Scoops of Django.
Have a file, such as, settings/common.py which will contain the properties/settings which are common in dev, prod and test environment. (You already have this.)
The other 3 files should:
Import the common settings from the settings/common.py by adding the line from .common import *
And should contain settings for its own corresponding environment.
The manage.py file decides which settings file to import depending on the OS environment variable, DJANGO_SETTINGS_MODULE. So, for test environment the value of DJANGO_SETTINGS_MODULE should be mysite.settings.test
Links for reference:
Django documentation for django-admin utility - Link
Two Scoops of Django sample project - Link
Preserve your settings folder structure and create __init__.py there.
Please, use code below in your settings/__init__.py:
import os
# DJANGO_SERVER_TYPE
# if 1: Production Server
# else if 2: Test Server
# else: Development Server
server_type = os.getenv('DJANGO_SERVER_TYPE')
if server_type==1:
from prod import *
elif server_type==2:
from test import *
else:
from dev import *
Now you can set environment variable called DJANGO_SERVER_TYPE to choose between Production, Test or Development Server and import settings using:
import settings
While I am working at localhost:8080, when I open interactive console and do some operations, like getting list of Kind etc (address: http://localhost:8080/_ah/admin/interactive) then it gives me this error:
<class 'google.appengine.dist._library.UnacceptableVersionError'>: django 1.2 was requested, but 0.96.4.None is already in use
This errors happened several times, in similar cases. It is stuck until restart localhost by dev_appserver.py
Is this a bug or what I am doing wrong?
Example for what I did at interactive console:
from myapp.models import *
for room in Room.all():
room.update_time = room.create_time
room.put()
Note:
This is my django_bootstrap :
import os
import sys
import logging
import __builtin__
from google.appengine.ext.webapp import util
import pickle
sys.modules['cPicle'] =pickle
logging.getLogger().setLevel(logging.INFO)
sys.path.insert(0, os.path.abspath((os.path.dirname(__file__))))
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from google.appengine.dist import use_library
use_library('django', '1.2')
import django.core.handlers.wsgi
def main():
application = django.core.handlers.wsgi.WSGIHandler()
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
my index.ymal in root folder says:
# AUTOGENERATED
# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run. If you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED"). If you want to manage some indexes
# manually, move them above the marker line. The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.
Thus each time I open http://localhost:8080/_ah/admin/datastore, this file updated: which is still has the same content but timestamp of file on operating system says it is updated.
I think here, As the http://localhost:8080 sees that models.py is not the same then it could load it then can not start django_bootstrap.
However if I first open http://localhost:8080/_ah/admin/datastore and then http://localhost:8080, it works. So this is why sometimes I get error sometimes not: It depends of order urls respective