Use models outside a view - django

To send emails and stuff, I use code outside the views.py file (too much code there). I created a file named "tools.py" in the app folder where I start with
from django.shortcuts import render_to_response
from django.core.mail import send_mail
from mysite.myapp.models import MyModel
With runserver, I have an error ImportError: cannot import name MyModel
This is strange as I use the same import in the views.py file and there is no problem...
Any idea ? Thanks

Most likely, you have a circular import. Are you importing this tools.py file in your myapp/models.py?

A couple of things:
Make sure you have your init.py file in the folder where your
"tools.py" file is located, this is a common reason why something might not be found.
I'm working on setting up something that requires something very similar to your requirements.
If you are trying to have this as a on/off process eg.) cronjob, worker etc. Do the following.
#!/usr/bin/env python
#########################################################################
# Required DO NOT REMOVE
#########################################################################
import os
import sys
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "appname.settings")
#########################################################################
# Import My Models, or Run an Include to Handle Processing.
from app.models.model import *
# Do Stuff to Test ( I suggest a simple insert into the model or pull and return content )
Save this file in the same folder that your "manage.py" is saved in, you can call this directly and it should process, you can setup a cronjob for it to run, etc. This allows you
to have a little less code as it doesn't run some of the processes that django runs prior to rendering a view from the urls.py file.
If this is unclear please feel free to comment and I will edit with correction or further details.
All the best

Related

import error when organizing django models in sperate files

Following the django docu I wanted to seperate my models into different files model1.py and model2.py. I also imported both of them in the __init__.py. But because they have a relationship, I need to import each of them in the other file. Now I get an error for from .model1 import Model1 that says
ImportError: cannot import name 'Model1'
is there a problem because I want to import within model2.py a class from model1.py that itself is importing from model2.py?
You might say, separating each model in a different file is normally not done in django. But I think it would be much better arranged when you have one file for one model.
This caused because of circular imports. from a import b and from b import a!. Please remove that by splitting the models properly.

Only in py.test file, usage of a nested(word?) imported variable/function fails with NameError

I have a python structure like this:
mymodule/
globalconfig.py # variables to set environment, etc
work.py # has: from mymodule.globalconfig import *
__init__.py
tests/
testspart1/
test_work.py # has: from mymodule.work import *
From inside work.py, all is well and I can access my global config variables and functions.
From inside test_work.py, I cannot access those variables, even if I add a second import,
from mymodule.globalconfig import *
Why is this? I wanted to use the same syntax as used in my modules.
thank you!
I am using py2.7 and, to get nice rspec-style outputs and verbose diffs,
pytest --spec -vv
Ref;
1.This answer reminded me I could use another format of import. If there are no other answers I will post my workaround. how to share a variable across modules for all tests in py.test
The import syntax that worked for me was directly importing the nested python file in addition to importing the file under test.
from mymodule.work import *
import mymodule.globalconfig as myconfigs
I assume it's a name clash or import circularity issue, but I could not figure out what the problem was. It took me a while so I wanted to be sure to post the solution for future me and others.

Test failure because model couldn't be imported

Application I am working on is proprietary and thus I will try to provide as much information as possible.
When running python manage.py test, which runs all the tests, only one application among many others fails. Too many hours have been burned on this.
The output is:
ImportError: Failed to import test module: app.aom.apps.forum.tests
after this, tracing is listed and then one line which says that the problem occurs when importing models into tests.py file, that is:
from .models import ForumSectionGroup, ForumSection, ForumThread, ForumPost
and the last line of the output is:
RuntimeError: Model class app.aom.apps.forum.models.ForumSectionGroup doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
I have Googled and researched what could cause this problem, and the conclusion: either I am importing module before application is loaded or I don't have the application listed in INSTALLED_APPS. But none of these seems to be the problem. Maybe testing mechanism somehow skips few steps and renders the model unloaded before importing it.
Explicitly assigning app_label as part of class Meta in the model results in conflict, because the model ends up registered twice, when I force it. I was driven to this conclusion by looking at the code at line 111, https://github.com/django/django/blob/master/django/db/models/base.py
I ran into this same issue. For me what fixed it was changing
from .models import Model1, Model2
to
from app.models import Model1, Model2
The from .model import syntax works fine in view.py, etc. but in the tests it was not working. This only seems to be the case when using a non-standard structure as pointed out in a comment above.
In my specific case I was using Django 1.11.

django get_model returns null when called from __.init__.py?

from django.db.models import get_model
modelname=get_model('base','reports')
The above code works fine in views.py and django shell,but returns null when called from init.py
folder structure is shown below
projectsfolder
--base
----models.py
----views.py
---- init.py
That can't possibly work. Anything in __init__.py is always going to be executed the first time anything in that directory is imported. But Django has to import the models in order to register them, so you've got into a chicken-and-egg situation: it won't register them until it imports them, but you're trying to get the models when they're imported...
Can you explain though why you don't simply do from models import Reports?
I still don't know why my code above doesn't work only # __init__.py.But the code below worked for me.
modelname=get_model('base', k['tablename'], seed_cache=False, only_installed=False).
Also django fixtures is a better way to initialise db. :):)

In django, how do I query a separate project from within my main project?

I have a project (#1) with a couple apps in it using a mysql database #1. I also have another project (#2) whose django code is on the same server, but it uses a different mysql database (#2).
My goal is to be running a web app in project #1 and use the django models from project #2 for a simple query against db #2. However, when I import from project #2, it still uses the #1 database, even though the settings.py file for #2 is appropriately using database #2 (i.e. when I run the web app in project #2, it works fine).
Here is the entirety of a file that I can successfully run as a standalone script. Sadly, when I import the file into project #1 and run the function, it fails (because it is looking in db#1 for the table):
import sys
def get_stuff_from_project2(ids):
from django.core.management import setup_environ
from project2 import settings
setup_environ(settings)
from project2.myapp2.models import mymodel2
all_rows = mymodel2.objects.filter(id__in=ids).values()
return(all_rows)
# as a standalone script, run the main function
if __name__ == "__main__":
sys.path.append("/home/me/django")
print str ( get_stuff_from_project2( sys.argv[1:] ) )
Again, this works as a standalone script. But, from project #1 (using code below) it fails with a DatabaseError, Table 'db1.myapp2_mymodel2' doesn't exist:
from project1.myapp1.standalone_script import get_stuff_from_project2
all_rows = get_stuff_from_project2( ids )
My guess here is that the setup_environ function does not actually process the new DATABASE_NAME, or that it can't change an existing DATABASE_NAME once the settings have been set?
I'm a bit lost at this point and have been trying to search for a solution. I don't really want to go down the "multi-site" or "multi-database" approach, since I would really like to keep project 1 and project 2 as separate as possible. My alternative would be to call the standalone script as a system call from within project 1, or to make a view in project 2 which is an API and sends data out. But, I thought that just using a model would be simplest if it worked.
Thanks.
------- added April 13, 11:35 PST ----
Here's a simpler version of the question: How can I access two different projects from a single standalone script. The following code works ok for whichever project I do setup_environ on first, but it can't do the second one:
import sys
from django.core.management import setup_environ
sys.path.append('/home/me/django')
from project1 import settings
print setup_environ(settings) # shows /home/me/django/project1
print settings.DATABASE_NAME # shows db1
from project1.myapp1.models import mymodel1
mymodel1.objects.filter(id=9376544).values() # works fine
from project2 import settings
print setup_environ(settings) # shows /home/me/django/project2
print settings.DATABASE_NAME # shows db2
from project2.myapp2.models import mymodel2
mymodel2.objects.filter(id=6544).values() # fails with:
# django.db.utils.DatabaseError: (1146, "Table 'db1.myapp2_mymodel2' doesn't exist")
I was unable to solve this using a single script. I instead used two scripts: the first called the second as a shell command, and the second output formatted data as a list to stdout.
This has been robust enough for the problem of reading a single stream of data from another app's database, but would not be suitable for a larger problem such as requiring several queries or writing to the second app's data. For the more complex problem, add APIs (XMLRPC, REST are easy in Django) to make calls into the running apps.
You have to add that other project to your pythonpath (in your wsgi file, for example, if you are using mod_wsgi, or in projects manage.py file if you want to access that project in "python manage.py shell" too). If you have done that it works like a magic.