Testing Django allauth - python

I am trying to test my app but not sure how to configure the django-allauth in the test environment. I am getting:
ImproperlyConfigured: No Facebook app configured: please add a SocialApp using the Django admin
My approach so far is to instantiate app objects inside tests.py with actual Facebook app parameters, an app which functions correctly locally in the browser:
from allauth.socialaccount.models import SocialApp
apper = SocialApp.objects.create(provider=u'facebook',
name=u'fb1', client_id=u'7874132722290502',
secret=u'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
apper.sites.create(domain='localhost:8000', name='creyu.org')
How can I get these tests running? Thanks

Where inside tests.py do you instantiate this app object? If it's inside the setUpModule() method, there shouldn't be a problem.
Personally, I would create a fixture init_facebook_app.json with the relevant information and then inside tests.py (before the test cases) define:
from django.core.management import call_command
def setUpModule():
call_command('loaddata', 'init_facebook_app.json', verbosity=0)
This ensures that the data in the fixture are loaded before the tests are run, and that they are loaded only once, i.e. not before each test. See this for reference regarding call_command.
Lastly, posting your Facebook app secret key anywhere on the internet is not a good idea - I would reset it if I were you.

I would create a migration so all your environments have the data
eg
import os
from django.db import models, migrations
from django.core.management import call_command
from django.conf import settings
class Migration(migrations.Migration):
def add_initial_providers(apps, schema_editor):
import pdb;pdb.set_trace()
call_command(
'loaddata',
os.path.join(settings.BASE_DIR, 'fixtures/social_auth.json'),
verbosity=0)
dependencies = [
('my_app', '001_auto_20160128_1846'),
]
operations = [
migrations.RunPython(add_initial_providers),
]

Related

How do I correctly import models in Python if I'm having such directories?

I'm using Django-REST framework with a telegram-bot in here. I need to import models from Django inside my telegram-bot file. I'm getting module not found error and probably thinking something wrong. Telegram-bot file is commands.py and the django models is models.py. The whole project looks like this:
Project directories
I just want to properly import models inside my commands.py file
Here is the possible solution for your question..
add following code inside my commands.py file
import sys
from django.apps import apps
from django.conf import settings
settings.configure(INSTALLED_APPS=['app_name'])
apps.populate(settings.INSTALLED_APPS)
from app_name.models import YourModel
also you may need to update path.
import sys
sys.path.append('path/to/your/django/project')
As you mentioned, You are using Django REST Framework, so you should try with a serializer file. import your model in serializer file, because the syntax is correct 'from app_name.models import YourModel'. Moreover, instead of settings.configure(INSTALLED_APPS=['app_name']) try this in settings.py
file in INSTALLED_APPS = 'app_name.apps.AppNameConfig'.

How can I use Django model externally from the app?

I have Django models Driver and Trip. Nothing in my views and no urls. I'm using Django as mere Database, using scripts to store stuff there in DB.
Here is my tree of how every thing looks:
loadmngr/
models.py
views.py
urls.py
management/
commands/
> it.py <
Assume I have init.py inside management and commands.
All I'm doing is a simple import of my Django models. Here is it.py:
import sys
parent = '/Users/work/TM/loadmngr'
sys.path.insert(0, parent)
from models import Trip
I run python manage.py it and I get a RunTimeError:
RunTimeError: Model class models.Driver doesn't declare an explicit app_label and either isn't in an application in INSTALLED_APPS or else was imported before its application was loaded.
The latter part of the error ...or else was imported before its application was loaded is what I believe could be the problem.
Question is: How can I properly use my Django models externally with properly configured settings?

dynamically loading django apps at runtime

Is it possible to dynamically load Django apps at runtime? Usually, apps are loaded at initialization, using the INSTALLED_APPS tuple in settings.py. However, is it possible to load additional apps at runtime? I am encountering this issue in different situations. One situation, for example, arises during testing, when I would like to dynamically load or unload apps.
In order to make the problem more concrete, imagine I have a directory called apps where I put my apps and I would like to automatically install any new app that goes in there without manually editing the settings.py.
This is easy enough. Following the example code in
Django: Dynamically add apps as plugin, building urls and other settings automatically
we put the following code in settings.py to could loop over the names of all sub-directories in the app directory and increment the INSTALLED_APPS tuple in settings.py like this:
APPS_DIR = '/path_to/apps/'
for item in os.listdir(APPS_DIR):
if os.path.isdir(os.path.join(APPS_DIR, item)):
app_name = 'apps.%s' % item
if app_name not in INSTALLED_APPS:
INSTALLED_APPS += (app_name, )
After that, if I was in a Django shell, I could something like
from django.conf import settings
and the apps would be listed in settings.INSTALLED_APPS. And if I did
from django.core import management
management.call_command('syncdb', interactive=False)
that would create the necessary DB tables for the apps.
However, if I were to now add some more apps to the apps/ directory, without re-starting, these would not be listed in settings.INSTALLED_APPS, and so a subsequent call to the syncdb would have no effect.
What I would like to know is if there is something I could do --- without restarting --- to reload the settings and load/install new apps.
I have tried to directly import my settings.py, i.e.
from myproject import settings
and then reload that settings using the python builtin after any app directory changes. Although settings.INSTALLED_APPS is now changed to include the newly added apps, this ultimately makes no difference. For example,
from django.db import models
models.get_apps()
shows only the original apps in apps and not the newly added ones and likewise
management.call_command('syncdb', interactive=False)
will not see the newly added apps.
As I stated above, I am thinking about this situation particularly in the context of testings where I dynamically would add or remove apps.
Ps. I working with Django 1.6, but on the advice of #RickyA, I see that there are some substantial changes to Django's treatment of applications in 1.7
https://docs.djangoproject.com/en/1.7/ref/applications/
I'm still not sure what this might mean for the problem I am facing.
Update for Django 1.8 on how to load an app that is not loaded yet
from collections import OrderedDict
from django.apps import apps
from django.conf import settings
from django.core import management
new_app_name = "my_new_app"
settings.INSTALLED_APPS += (new_app_name, )
# To load the new app let's reset app_configs, the dictionary
# with the configuration of loaded apps
apps.app_configs = OrderedDict()
# set ready to false so that populate will work
apps.ready = False
# re-initialize them all; is there a way to add just one without reloading them all?
apps.populate(settings.INSTALLED_APPS)
# now I can generate the migrations for the new app
management.call_command('makemigrations', new_app_name, interactive=False)
# and migrate it
management.call_command('migrate', new_app_name, interactive=False)
With Django 2.2 this work for me
from collections import OrderedDict
from django.apps import apps
from django.conf import settings
from django.core import management
new_app_name = "my_new_app"
settings.INSTALLED_APPS += (new_app_name, )
apps.app_configs = OrderedDict()
apps.apps_ready = apps.models_ready = apps.loading = apps.ready = False
apps.clear_cache()
apps.populate(settings.INSTALLED_APPS)
management.call_command('makemigrations', new_app_name, interactive=False)
management.call_command('migrate', new_app_name, interactive=False)
To answer my own question...
While I do not have a completely general solution to this problem, I do have one that is sufficient for the purposes of dynamically loading apps during testing.
The basic solution is simple, and I found it at a wee little bixly blog.
Continuing with my example above, if I was in a django shell and wanted to add and load some new apps that were added to my apps directory, I could do
import os
from django.conf import settings
from django.db.models import loading
from django.core import management
APPS_DIR = '/path_to/apps/'
for item in os.listdir(APPS_DIR):
if os.path.isdir(os.path.join(APPS_DIR, item)):
app_name = 'apps.%s' % item
if app_name not in settings.INSTALLED_APPS:
settings.INSTALLED_APPS += (app_name, )
and then
loading.cache.loaded = False
management.call_command('syncdb', interactive=False)
It is possible to dynamically load and unload applications in tests in Django >= 1.7 (and also in the current 4.1) by a override_settings() decorator:
#override_settings(INSTALLED_APPS=[...]) # added or removed some apps
class MyTest(TestCase):
# some tests with these apps
def test_foo(self):
pass
It has been possible since September 2014, not before the question.
Many other topics from the question are solved by django.apps also in Django >= 1.7. Generally: Dynamic configuration at startup is easy in the current Django. Dynamic loading and unloading after startup can't be recommended in production, even that it could work eventually.
Yes! Anything (or almost everything) in Python is possible. You should use os.walk() in order to get all folders, subfolders and files within your apps path in order to get all of your apps including the nested ones.
def get_installed_apps():
from os import walk, chdir, getcwd
previous_path = getcwd()
master = []
APPS_ROOT_PATH = '/my/project/apps/folder'
chdir(APPS_ROOT_PATH)
for root, directories, files in walk(top=getcwd(), topdown=False):
for file in files:
if 'apps.py' in file:
app_path = f"{root.replace(BASE_DIR + '/', '').replace('/', '.')}.apps"
print(app_path)
master.append(app_path)
chdir(previous_path)
return master
print(get_installed_apps())

How can I use Flask Admin panel in a different package?

This is my application structure:
/blog
/blog
/app.py
models.py
views.py
/admin
__init__py
views.py
...
I want to use flask-admin extension in a different package.
in /admin/__init__.py I imported the app and flask-admin extension:
from flask.ext.admin import Admin
from app import app
then I initiate the admin app like that:
admin = Admin(app)
However, I get 404 error. Why? Should I use blueprint or what?
I assume you're trying to hit the default /admin routes within your Flask app for Flask admin?
My guess right now is that none of your code does import admin anywhere, which is probably good since admin's __init__.py will try to re-import your app.py all over again (from the from app import app reference) and you'll end up in a circular dependency.
What I'd do is alter app.py to contain the admin = Admin(app) and from flask.ext.admin import Admin code, and also do a from admin import views and empty out the admin/__init__.py file completely.

Unit testing Django templates in Google App Engine raises TemplateDoesNotExist(name)

I am trying to set up unit testing of a series of Django templates in Google App Engine using the python unittest framework.
The app uses python 2.7, webapp2, Django 1.2, and is already using unittest for testing the none Django functionality. The Django templates have no issues serving through the server in dev and live environments.
When executing the page call through the unittest framework the following error is raised:
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django_1_2/django/template/loader.py", line 138, in find_template
raise TemplateDoesNotExist(name)
TemplateDoesNotExist: site/index.html
Settings.py:
import os
PROJECT_ROOT = os.path.dirname(__file__)
TEMPLATE_DIRS = (
os.path.join(PROJECT_ROOT, "templates"),
)
Unit test call:
import webapp2
import unittest
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from google.appengine.dist import use_library
use_library('django', '1.2')
import main
class test_main(unittest.TestCase):
def test_default_page(self):
request = webapp2.Request.blank('/')
response = request.get_response(main.app)
self.assertEqual(response.status_int, 200)
I've found it necessary to specify DJANGO_SETTINGS_MODULE and the Django version within the test file even though these are normally specified through app.yaml
The page handler:
from django.template.loaders.filesystem import Loader
from django.template.loader import render_to_string
class default(webapp2.RequestHandler):
def get(self):
self.response.out.write(render_to_string('site/index.html'))
I've tried stripping everything out of index.html but still get the same error.
I've tried using an explicit path for TEMPLATE_DIRS but no change.
Any ideas?
Check if this is set anywhere in your django config:
TEMPLATE_LOADERS=('django.template.loaders.filesystem.load_template_source',)

Categories