I have a django app with multiple databases and i have begun to use django-constance to use 'live' settings in mi project.
I have seen in documentation, it seems possible change the default database to save the settings models. But it's always save the model in default. Is it really possible?
If you have multiple databases you can set what databases will be used
with CONSTANCE_DBS
CONSTANCE_DBS = “default”
DATABASES = {"default": {},
"config": {}}
CONSTANCE_DBS = "config"
Related
I've implemented API using Django REST Framework that I use for my project which is a Flutter app.
*BUT, I want to add some data from another Server's database, can I do it in Django REST Framework, and then include those in my API ?
You can set multiple databases in settings.py file.
DATABASES = {
'default': {
...
},
'other': {
...
}
}
And you need to create another app other and define the models in models.py of the newly created project folder. Let's say, you defined a Sport model in other app.
Then in views.py file you can refer to this model.
from other.models import Sport
# in one of your api view
def SomeView(...):
...
Sport.objects.using('other').create(...)
The main code is using('...').
Note: You don't need to make migrations for the other app when you need to make migrations.
I have several Django applications and they need to share one database on Heroku. I may specify the shared database on each statement that need to access it, for example:
from account.models import User
if DEBUG: # Running locally
users = User.objects.all() # 'default' DB
else: # Running on Heroku
users = User.objects.using('shared').all() # 'shared' DB
I have two questions:
1) Specifying the shared database on every statement is really tedious. Is it possible to set the shared database once for all (maybe in setting.py)? For example:
from account.models import User
if not DEBUG: # Running on Heroku
User = User.objects.using('share') # This is hypothetical!!
users = User.objects.all()
2) How do I set the shared DB for a foreign key. For example:
from account.models import User
class Article(models.Model):
author = models.ForeignKey(User) # How to set 'User' to come from 'shared' DB?
Django database routers have what you are looking for
https://docs.djangoproject.com/en/2.0/topics/db/multi-db/#using-routers\
Relations do not work cross database
https://docs.djangoproject.com/en/dev//topics/db/multi-db/#limitations-of-multiple-databases
I recommend trying to keep everything in 1 database initially. Usually when starting out there isn't going to be a need to separate it out.
I am trying to work with Sites Model of Django.
I dont quite understand why SITE_ID should be SITE_ID = 1.
in the docs:
The ID, as an integer, of the current site in the django_site database
table. This is used so that application data can hook into specific
sites and a single database can manage content for multiple sites.
why 1? what is the current site? this is not clearly explained in the docs.
lets say, I have www.coolsite.com and some other subdomains like www.wow.coolsite.com and www.awesome.coolsite.com
I want to render different content depending on domain name.
my question is, or better, are:
Do I have to add all those domains into Sites Table in DB?
if so, how should I set SITE_ID in settings? Do I have to set all ids like SITE_ID = 1, SITE_ID = 2.. etc?
what does current site has to do with SITE_ID = 1?
I am a bit confused here.
I thought, each Site (e.g. www.wow.coolsite.com) should be a separate django project so that they can have their own settings.py? and in each of those settings.py's, I will set the id of that page from Sites table? but then there are many django projects which also doesnot make sense to me.
Django was created from a set of scripts developed at a newspaper to publish content on multiple domains; using one single content base.
This is where the "sites" module comes in. Its purpose is to mark content to be displayed for different domains.
In previous versions of django, the startproject script automatically added the django.contrib.sites application to INSTALLED_APPS, and when you did syncdb, a default site with the URL example.com was added to your database, and since this was the first site, its ID was 1 and that's where the setting comes from.
Keep in mind that starting from 1.6, this framework is not enabled by default. So if you need it, you must enable it
The SITE_ID setting sets the default site for your project. So, if you don't specify a site, this is the one it will use.
So to configure your application for different domains:
Enable the sites framework
Change the default site from example.com to whatever your default domain is. You can do this from the django shell, or from the admin.
Add your other sites for which you want to publish content to the sites application. Again, you can do this from the django shell just like any other application or from the admin.
Add a foreign key to the Site model in your object site = models.ForeignKey(Site)
Add the site manager on_site = CurrentSiteManager()
Now, when you want to filter content for the default site, or a particular site:
foo = MyObj.on_site.all() # Filters site to whatever is `SITE_ID`
foo = MyObj.objects.all() # Get all objects, irrespective of what site
# they belong to
The documentation has a full set of examples.
Things would be much easier to understand if Django's default SiteAdmin included the id field in the list_display fields.
To do this, you can redefine SiteAdmin (anywhere in your app, but I'd recommend your admin.py or maybe your urls.py) like this:
from django.contrib import admin
from django.contrib.sites.models import Site
admin.site.unregister(Site)
class SiteAdmin(admin.ModelAdmin):
fields = ('id', 'name', 'domain')
readonly_fields = ('id',)
list_display = ('id', 'name', 'domain')
list_display_links = ('name',)
search_fields = ('name', 'domain')
admin.site.register(Site, SiteAdmin)
After including this code snippet, the ID for each "Site" will be shown in the first column of the admin list and inside the form as a read only field. These 'id' fields are what you need to use as SITE_ID:
The concept is that each different site runs in a different application server instance, launched using a different yourdomain_settings.py that then includes a base_settings.py with the rest of the common configuration.
Each of these yourdomain_settings.py will define its own SITE_ID and all other different settings.py parameters that they need to look and be different from each other (static resources, templates, etc.) then you'll define a DJANGO_SETTINGS_MODULE environment variable pointing to that specific yourdomain_settings.py file when launching the application server instance for that domain.
A further note: get_current_site(request) does need request to be available for it to work. If your code doesn't have one, you can use Site.objects.get_current() that however will need a SITE_ID properly defined in the running application server's settings.
This is a late answer but for anyone else having SITE_ID issues and Site problems.
Inside the database, django has a django_site table with(id, domain, name). This is where django stores the SITE_IDs. Mine was actually 5 in the database but i had it set to SITE_ID=1 in the settings.
Knowing that, i can now go back to the database and clear it to get back to zero or use the actual id in the database.
This is covered in the documentation for the Sites framework:
In order to serve different sites in production, you’d create a
separate settings file with each SITE_ID (perhaps importing from a
common settings file to avoid duplicating shared settings) and then
specify the appropriate DJANGO_SETTINGS_MODULE for each site.
But if you didn't want to do it that way, you can not set SITE_ID at all and just look up the current site based on the domain name in your views using get_current_site:
from django.contrib.sites.shortcuts import get_current_site
def my_view(request):
current_site = get_current_site(request)
if current_site.domain == 'foo.com':
# Do something
pass
else:
# Do something else.
pass
This link explains it:
You’ll want to create separate settings files for each domain you’re adding; each one will need its own MEDIA_URL and other settings. You’ll also want to do two things to make sure everything works out properly for administering the different sites:
Create a new Site object in your admin for each domain, and put the id of that Site into its settings file as SITE_ID so Django knows which site in the database corresponds to this settings file.
In the settings file for your original site (the one with id 1), add the other sites’ settings files to the ADMIN_FOR setting, to let Django know that this one instance of the admin application will handle all of the sites.
Also, if you wanna figure out how to modify models and set the views You may take a look at this link:
https://django.cowhite.com/blog/managing-multiple-websites-with-a-common-database-in-django-the-sites-framework/
I have a Django project for a simple blog/forum website I’m building.
I’m using the syndication feed framework, which seems to generate the URLs for items in the feed using the domain of the current site from the Sites framework.
I was previously unaware of the Sites framework. My project isn’t going to be used for multiple sites, just one.
What I want to do is set the domain property of the current site. Where in my Django project should I do that? Somewhere in /settings.py?
If I understand correctly, Sites framework data is stored in the database, so if I want to store this permanently, I guess it’s appropriate in an initial_data fixture.
I fired up the Django shell, and did the following:
>>> from django.contrib.sites.models import Site
>>> one = Site.objects.all()[0]
>>> one.domain = 'myveryspecialdomain.com'
>>> one.name = 'My Special Site Name'
>>> one.save()
I then grabbed just this data at the command line:
python manage.py dumpdata sites
And pasted it into my pre-existing initial_data fixture.
The other answers suggest to manually update the site in the admin, shell, or your DB. That's a bad idea—it should be automatic.
You can create a migration that'll do this automatically when you run your migrations, so you can be assured it's always applied (such as when you deploy to production). This is also recommended in the documentation, but it doesn't list instructions.
First, run ./manage.py makemigrations --empty --name UPDATE_SITE_NAME myapp to create an empty migration. Then add the following code:
from django.db import migrations
from django.conf import settings
def update_site_name(apps, schema_editor):
SiteModel = apps.get_model('sites', 'Site')
domain = 'mydomain.com'
SiteModel.objects.update_or_create(
pk=settings.SITE_ID,
defaults={'domain': domain,
'name': domain}
)
class Migration(migrations.Migration):
dependencies = [
# Make sure the dependency that was here by default is also included here
('sites', '0002_alter_domain_unique'), # Required to reference `sites` in `apps.get_model()`
]
operations = [
migrations.RunPython(update_site_name),
]
Make sure you've set SITE_ID in your settings. Then run ./manage.py migrate to apply the changes :)
You can change it using django admin site.
Just go to 127.0.0.1:8000/admin/sites/
For those who are struggling to find "Sites" section on Django's admin page, for newer Django versions you need to enable the optional Sites Framework like so:
On your settings.py file, add this to your "INSTALLED_APPS":
'django.contrib.sites'
Then specify an ID for the default site (since it's probably your first site to be specified, you can use ID 1):
SITE_ID = 1
Run your migrations and check if the "Sites" section is available on your Django's admin page.
More details at https://docs.djangoproject.com/en/3.0/ref/contrib/sites/#enabling-the-sites-framework
You can modify the Site entry in your database manually. Navigate to the table called 'django_site'. Then, you should only see one entry (row). You'll want to modify the field (column) named 'domain'.
In django models we have option named managed which can be set True or False
According to documentation the only difference this option makes is whether table will be managed by django or not. Is management by django or by us makes any difference?
Is there any pros and cons of using one option rather than other?
I mean why would we opt for managed=False? Will it give some extra control or power which affects my code?
The main reason for using managed=False is if your model is backed by something like a database view, instead of a table - so you don't want Django to issue CREATE TABLE commands when you run syncdb.
Right from Django docs:
managed=False is useful if the model represents an existing table or a database view that has been created by some other means. This is the only difference when managed=False. All other aspects of model handling are exactly the same as normal
When ever we create the django model, the managed=True implicitly is
true by default. As we know that when we run python manage.py makemigrations the migration file(which we can say a db view) is
created in migration folder of the app and to apply that migration i.e
creates the table in db or we can say schema.
So by managed=False, we restrict Django to create table(scheme, update
the schema of the table) of that model or its fields specified in
migration file.
Why we use its?
case1: Sometime we use two db for the project for
example we have db1(default) and db2, so we don't want particular
model to be create the schema or table in db1 so we can this or we can
customize the db view.
case2. In django ORM, the db table is tied to django ORM model, It
help tie a database view to bind with a django ORM model.
Can also go through the link:
We can add our raw sql for db view in migration file.
The raw sql in migration look like: In 0001_initial.py
from future import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.RunSQL(
CREATE OR REPLACE VIEW app_test AS
SELECT row_number() OVER () as id,
ci.user_id,
ci.company_id,
),
]
Above code is just for overview of the looking of the migration file, can go through above link for brief.