Django-rest-framework - fetching data from another server's DB - django

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.

Related

Django - Model.py

Just a simple question.
After I connect my django app to a remote database, I don't need to use Model.py to create tables in the database, then what is the function for Model.py at that moment?
If you want to use the Django ORM, you'll need to create models in the models.py file that match your remote database. If you don't want django creating or deleting tables on this DB, the managed=False option needs to be set for each model.
https://docs.djangoproject.com/en/1.11/ref/models/options/#managed
As you said after running migrations all tables in models.py file will be created. Later on, if you want to do some database operations, you may be using Django ORM. If you don't have models.py you won't be able to do such operations.
For example:
To create an entry to the table MyModel.
from your_app.models import MyModel
MyModel.objects.create(<field_name>=<value>)
I hope this gives you some idea.

How to prepopulate test database by necessary data?

I need to do some unit tests in my Django project. The problem is that almost every use case depends on prepopulated database objects.
For example, I want to create a product and test, if there were all pre_save signals successful.
from django.contrib.auth.models import User
from django.test import TestCase
from .models import Product
class ProductTestCase(TestCase):
def setUp(self):
self.user = User.objects.create(username='test_user')
self.product = Product.objects.create(name='Test product',user=self.user)
def test_product_exists(self):
self.assertIsNotNone(self.product)
def product_is_active_by_default(self):
...
I can't do that because product has to have User object related. But I can't create a User object because User has to have related plan object. There are multiple plans in my production database from which one is default but there are no plans inside test database.
So to be able to do unit tests I need to prepopulate test database with multiple objects from multiple apps.
How can I do that?
you can simply use django fixtures for that :-)
first populate a sample db with data then export data with python manage.py dumpdata
then in one of your apps create a directory named fixtures and put exported json file there (named tests.json or something else)
in your test class load fixtures like this
class ProductTestCase(TestCase):
fixtures = ['tests.json', ]
checkout django docs
PS: checkout factory boy too (#Gabriel Muj) answer
I don't recommend using fixture since you will need to maintain them each time you make changes to the model. Here is a better approach on creating objects for tests by using this library https://factoryboy.readthedocs.io/en/latest/ which is more flexible.

Do something once in django

I want to create two groups once per project's life. So, I read about AppConfig
And I created core.appconfig.py:
from django.apps import AppConfig
from django.contrib.auth.models import Group
class RolesConfig(AppConfig):
name = 'roles_config'
verbose_name = 'Roles configuration'
def create_roles(self):
driver = Group.objects.create(name='driver')
manager = Group.objects.create(name='manager')
driver.save()
manager.save()
And the in settings.py: default_app_config = 'core.appconfig.RolesConfig'
But when I run server and go to the admin page, there are no groups. Why? When is AppConfig called?
Consider using a data migration:
Create an empty migration file with manage.py makemigrations <app_name> --empty.
Create a function that adds the default values to the database.
def create_roles(apps, schema_editor):
Group = apps.get_model('auth', 'Group')
driver = Group.objects.create(name='driver')
manager = Group.objects.create(name='manager')
Add a RunPython operation to you migrations:
class Migration(migrations.Migration):
operations = [
migrations.RunPython(create_roles),
]
Automatic loading of data fixtures has been deprecated in favour of data migrations.
I consider #Leistungsabfall answer to be correct, apart from that: don't do this. App config was not built for this purpose, instead you should create fixtures: https://docs.djangoproject.com/en/1.8/howto/initial-data/ .
App config is run every time you run the application so it would not really work.
There are several things wrong here:
Make sure the path to appconfig.py is myapp/appconfig.py.
Make sure that name is your Django application name (e.g. myapp).
Rename create_roles(self) to ready(self).
In myapp/__init__.py (create this file if it doesn't exist) add this line:
default_app_config = 'myapp.appconfig.RolesConfig'
Remove driver.save() and manager.save(), they are redundant because create() already does save the objects in the database.
(Replace myapp with your Django application name.)

programatically accessing Django models from another app

I have a moderately complicated Django project with a variety of different apps (app1, app2 etc), each with their own models. I am building a MetaApp app to track info about each app, with a MetaApp class in models.py, and fields such as appname and modelname
MetaApp drives an index view that summarizes various aspects of each project. I would like to include a count of the database records for each app. This means that I need to programmatically access models from other apps. If I I know the appname and modelname, how do I programmatically access these models?
projects = MetaApp.objects.all()
projects[0].appname[0].modelname.ojects.all()
This code results in an attribute error, because I am storing the appname and modelname as unicode strings. What is the workaround?
Use the django.db.models.loading.get_model() function:
from django.db.models.loading import get_model
model = get_model(app_name, model_name)
object_list = model.objects.all()

Where do I set the domain for my Django Sites framework site, when I only have one?

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'.