Django django.contrib.sites where to put migration? - python

the django doc says to change the sites name and domain in the django.contrib.sites framework one should use a migration [1].
But they forgot to mention where I should put this migration. I tried to create a directory named "sites" and a directory named "django.contrib.sites". But no matter in which directory I put my migration, manage.py migration always says there is nothing to update.
I also tried to run python manage.py makemigrations --empty sites, but then the migration is created in the lib directory: ve/lib/python3.5/site-packages/django/contrib/sites/migrations/0003_auto_20160904_2144.py. This may be correct behaviour, but then I cannot set my change under source control.
In case something is wrong with my migration, here it is:
from __future__ import unicode_literals
from django.db import migrations, models
def set_site_name(apps, schema_editor):
Sites = apps.get_model('django.contrib.sites', 'site')
site = Sites.objects.filter(id=1).first()
if site != None:
site.name = "name"
site.domain = "name.com"
class Migration(migrations.Migration):
initial = True
operations = [
migrations.RunPython(set_site_name),
]
So my question is: where does django expect to find those migrations?
Thank you very much in advance for your help.
[1] https://docs.djangoproject.com/en/1.10/ref/contrib/sites/#enabling-the-sites-framework

Each app in a Django project must have a unique label. Naming your app sites isn't a good idea - it will clash with the django.contrib.sites app unless you change the label in the app config class.
If you have an existing app specific to your project, you could use that app to store the data migration.
Alternatively choose a different name like mysites. Create the app with ./manage.py startapp mysite, add the app to your INSTALLED_APPS, then create a blank migration.

Related

django.db.utils.OperationalError: no such table: django_site_id_seq

I got this error when running command python manage.py test for testing purpose.
I tried after delete my pycache and migration files and db.sqlite3 then run the python manage.py makemigrations and python manage.py migrate again as well.
But still got the same error...
Here is my test.py
from rest_framework.test import APITestCase
from django.urls import reverse
from rest_framework import status
# Create your tests here.
class UserTest(APITestCase):
def setUp(self):
register_url = reverse('user:register')
data = {
"username":"Tester",
"email":"tester#gmail.com",
"password":"tester123",
"mobile_number":"03322917356"
}
self.client.post(register_url, data, format='json')
def test_user_can_register(self):
register_url = reverse('user:register')
data = {
"username":"Tester1",
"email":"tester1#gmail.com",
"password":"tester123",
"mobile_number":"03322911356"
}
response = self.clent.post(register_url , data , format='json')
self.assertEqual(response.status_code ,status.HTTP_201_CREATED)
Try switching to postgresql, to see if it is a database issue always good to try something else. if that doesn’t work then I would get an existing example that does work and compare it from there to what you have. tbh unless you have your code opensource it is difficult to debug something like this without speculation as a lot of different systems are affected when ensuring migrations are applied. Check your migrations files to see if those are indeed correct. they should be under /migrations
Have you added your app in settings.py to installed apps?
In hour installed app comment out django sites. Do makemigrations and migrate. Then reactivate django sites and do the migration stuff again

Apply a migration to Django Flatpage model

I would like to use the modeltranslation package in a Django application that uses the flatpages app.
I installed both, followed the model translation docs, and created a translation.py file, which I put in the main app (where all the global stuff lies), as I can't put it directly in the flat pages app (Django code is a requirement and is not committed to VCS).
# django/main/translation.py
from modeltranslation.translator import translator, TranslationOptions
from django.contrib.flatpages.models import FlatPage
class FlatPageTranslationOptions(TranslationOptions):
fields = ('title', 'content')
translator.register(FlatPage, FlatPageTranslationOptions)
Then I ran python manage.py makemigrations, and it created a migration file in the flatpages app /usr/local/lib/python3.8/site-packages/django/contrib/flatpages/migrations/0002_auto_20211118_1558.py. It would be again in the Django code, so I tried to simply move it to the main app at django/main/migrations/0002_flatpages_translations.py (there is already an unrelated 0001_initial.py migration, which has no dependencies):
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('flatpages', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='flatpage',
name='content_en',
field=models.TextField(blank=True, null=True, verbose_name='content'),
),
migrations.AddField(
model_name='flatpage',
name='content_fr',
field=models.TextField(blank=True, null=True, verbose_name='content'),
),
migrations.AddField(
model_name='flatpage',
name='title_en',
field=models.CharField(max_length=200, null=True, verbose_name='title'),
),
migrations.AddField(
model_name='flatpage',
name='title_fr',
field=models.CharField(max_length=200, null=True, verbose_name='title'),
),
]
And... when I finally try to run the migration (python manage.py migrate), I got this error:
CommandError: Conflicting migrations detected; multiple leaf nodes in the migration graph: (0001_initial, 0002_flatpages_translations in main).
To fix them run 'python manage.py makemigrations --merge'
I tried the --merge flag, but got another error: ValueError: Could not find common ancestor of ['0001_initial', '0002_flatpages_translations']
Is it possible to achieve what I want to do?
Found a solution, so I post it here if someone has the same problem. According Django documentation, you can specify the package where migration modules can be found on a per-app basis.
So, in settings.py, add:
MIGRATION_MODULES = {
'flatpages': 'main.migrations.flatpages',
}
Then move the migration file 0002_flatpages_translations.py in django/main/migrations/flatpages/. In the case of the flatpages app, you will also need to copy the 0001_initial.py migration file from the flatpage app, inside this directory.
And you're good, Django now searches the migrations for the flatpages app in your new directory.

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?

Extending Customer's view from Django-Oscar

I am trying to override customer app in django-oscar. For that I have created customer app in my apps folder in project. While I run that project I encountered an error in django 1.7.4 as below:
django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: customer
I went through the doc in django https://docs.djangoproject.com/en/1.7/ref/applications/#django.apps.AppConfig, But its not working out. So Is there any other way to extend any django-oscar's app and modify the code as per requirements.
This is my customer app's views.py:
from oscar.apps.customer.views import ProfileView as CoreProfileView
class ProfileView(CoreProfileView):
template_name = 'new_account.html'
and below is project's settings.py code snippet:
INSTALLED_APPS = [
'apps.customer',
]
Thanks in advance.
Run this command to overide apps from django oscar
./manage.py oscar_fork_app appname yourprojectname
yourprojectname-Your folder path to where the app should be created
Once you run this command a new app will be created with overided models,admin files.now add the app path inside
get_core_apps(['yourproject.order']) in settings.py file.
For more information please refer
http://django-oscar.readthedocs.org/en/latest/topics/customisation.html

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())

Categories