Django model foreign key from existing table - python

In my django project I use django-registration reusable app. I install this app and run syncdb. It's create for me table 'registration_registrationprofiles' in my database. Then I create a new app and write this code in my models.py:
class Comments(models.Model):
text = models.TextField()
pub_date = models.DateTimeField(auto_now=True)
user = models.ForeignKey('registration_registrationprofiles')
And run manage.py makemigrations and it throw me exception:
ERRORS:
comments.Comments.user: (fields.E300) Field defines a relation
with model 'registration_registrationprofiles', which is either
not installed, or is abstract.
How I can fix this problem?

Try this:
from registration.models import RegistrationProfile
and then:
user = models.ForeignKey(RegistrationProfile)

Migrations can have dependencies declared. Usually, makemigrations does a good job with that, but it looks like it missed it this time. I suggest you locate the migration file it created (in your_app/migrations) and check its dependencies. It should look like this:
class Migration(migrations.Migration):
dependencies = [("registration", "0042_some_migration")]
# operations...
The key here it the dependencies array should reference the registration app, and the latest migration (or at least the latest you depend on).
Then manage.py makemigrations will detect the dependency and run migrations in the correct order.

Related

Switch to another database in Django

I have a django project that was created on an Oracle database and I want to switch to ANOTHER Oracle database. I have followed this tutorial https://pythonfusion.com/switch-database-django/, but there is a problem that not all models are created initially in Django, some are created using inspectdb on existing tables in other databases . Therefore, when using the migrate --database=new command, I get errors about those tables that already existed before Django was created. Is there a way to migrate only the models and tables necessary for Django to work? (users, auth...)
I think you have to take a look at the managed attribute of each model meta class.
If managed is true then django will change the model in the database.
Unmanaged model :
class MyModel(models.Model):
...
class Meta:
managed = False # This means django will ignore MyModel when migrating
Managed model :
class MyManagedModel(models.Model):
...
class Meta:
managed = True # This means django will migrate MyManagedModel
More documentation here : https://docs.djangoproject.com/en/4.1/ref/models/options/
Yes you can definitely customize your migration behavior, the command python manage.py makemigrations creates a couple of files that are used to migrate your models into your DB, any who you can still access these files and choose exactly what to include, exclude and even edit them.
Check the following link:
https://dev.to/koladev/writing-custom-migrations-in-django-3eli
If I've understood your question correctly, then you're looking to use Django's built-in migrations. To find out which migrations have been run against your new database, run the command manage.py showmigrations --database=new which will show you a list of all migrations that exist within the context of your application.
Once that is done, you can manually run the desired migrations (e.g. auth and contenttypes) by running the command manage.py migrate --database=new app_label migration_name.
showmigrations command: https://docs.djangoproject.com/en/4.1/ref/django-admin/#django-admin-showmigrations
migrate command: https://docs.djangoproject.com/en/4.1/ref/django-admin/#django-admin-migrate

Set initial (default) instances in django admin

I am building a Blog App and I am trying to add inbuilt initial instances in django admin so when user clone the repo , then user will see several initial blogs every time even after reset the database.
I didn't find anywhere to set the initial data. I also tried How to set initial data for Django admin model add instance form? But it was not what i am trying to do.
models.py
class BlogPost(models.Model):
title = models.CharField(max_length=1000)
body = models.CharField(max_length=1000)
I tried to use Providing data with fixtures But I have no idea , How can I store in.
Any help would be much Appreciated. Thank You.
Fixtures still need to be loaded manually. You can add that step into installation instruction, something like "to load example data, install the provided fixture via manage.py loaddata ./my_blog_fixture.json
If you want to have the data inserted into database without any user's action, then you are looking for a Data Migration
that's a kind of database migration which does not change the database structure in any way, but it executes a custom command, eg. inserting some data. An example (adjustments needed to match your app name) below. You can either generate an empty migration (recommended) or append RunCommand into an existing migration.
To generate a new empty migration run makemigrations
$ manage.py makemigrations your_app_name --empty
then edit the migration and add RunPython there (see linked docs above).
from django.db import migrations
def insert_blogpost(apps, schema_editor):
BlogPost = apps.get_model('your_app_name', 'BlogPost')
post = BlogPost(title="hello", body="post content")
post.save()
class Migration(migrations.Migration):
dependencies = [
('your_app_name', '0001_initial'),
]
operations = [
migrations.RunPython(insert_blogpost),
]

Django 1.8 migration strange behaviour

I am trying to modify an existing School app which has sub-apps like students, class, scores etc using django 1.8.
My class model:
class Class(Object):
student = models.ForeignKey(School, related_name='school_student')
section = models.CharField()
roll = models.IntegerField()
When I run python manage.py makemigrations class, I am getting a message No changes detected in app 'class'.
But when I run python manage.py makemigrations, the changes are detected and the migration files are created under the school directory but not in the class directory.
But when to the above model if I add a meta class.
class Meta:
unique_together = ('student', 'roll')
And now if I run python manage.py makemigrations class, the changes are detected and the migration files are created under the class directory.
Can someone tell me why such behaviour?
First of all: A model is not a subapp.
If that's clear: IIRC, Django 1.8 requires a class Meta to know which app a model belongs to.
If you only have an additional model, you need class Meta to specify the app_label.
If you have a real subapp (i.e. an app within a app), you also need to add it to settings.INSTALLED_APPS for their migrations to work properly.

Issue setting up a django database migration for an app with a model that has a relationship to another app in the same project

I'm trying to setup two related apps in a django project, where one app's model references the other in a foreign key relationship. This is normally a simple thing, but I'm running into some collisions with app names (one of my apps is called 'account' and that's not unique in my installation) and my subsequent fix to that by adding in specific name/label definitions in a custom AppConfig may also be contributing to the problem.
A little background on my environment:
Django 1.8.3
Python 2.7.6
Postgres 9.4.0
using this template for my project structure: https://github.com/pydanny/cookiecutter-django. Thanks pydanny!
I setup a simple project using this template to demonstrate the problem: https://github.com/rishikumar/django_test_model
Here are the relevant parts to the tree:
test/ (project app)
/config ()
/test (main django app)
/account
__init__.py
apps.py
models.py (Has a model called "Account")
/schedule
__init__.py
apps.py
models.py (Has a model called "Schedule" which has a ForeignKey relationship to the Account table)
Here is the first model class, under the test/account app
class Account(models.Model):
class Meta:
db_table = 'test_account'
After putting this in place, I added this project to the INSTALLED_APPS as "test.account". I ran makemigrations next.
./manage.py makemigrations test.account
I was expecting this to uniquely identify the account package underneath the test project, but its only looking for the "account" part of the name. (I couldn't find any documentation explaining why this is the case)
django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: account
To work around this problem I setup a custom AppConfig for this. in test/test/account/init.py I added the following:
default_app_config = 'test.account.apps.AppConfig'
And to test/test/account/apps.py I added:
class AppConfig(apps.AppConfig):
name = 'test.account'
label = 'test.account'
Now I can run make migrations as I originally intended and it works as expected.
./manage.py makemigrations test.account
Incidentally, I gave the model a specific table name because it was specifying "test.account_account" by default and that causes some headaches in the postgres CLI - I have to quote the entire table name to reference it.
I setup the second app the same way - added a default app config and setup the name and label of the app config to be "test.schedule"
Here is the models.py in the schedule app:
from test.account.models import Account
class Schedule(models.Model):
class Meta:
db_table = 'test_schedule'
account = models.ForeignKey(Account)
Now I run makemigrations on this app:
./manage.py makemigrations test.schedule
I get the following error:
ValueError: Lookup failed for model referenced by field test.schedule.Schedule.account: test.schedule.test.account.Account
Notice that the Account class that its trying to access says "test.schedule.test.account.Account" when it should referencing "test.account.Account"
I'm not sure if my solution for the AppConfig entry was the right choice - perhaps there is a better way to uniquely identify an app within the django installation?
I'm guessing that I'm making a bad decision about how to name things in my AppConfig, but I'm not sure how to reconcile the fact that I need to specify an AppConfig to avoid having duplicate application labels while still being able to avoid confusing the lookup for the foreign key reference that the migration tool is using.

Django many to many relationship with built in "User" model

Scenario
I have a basic Django app in which users (django's authentication built in model) and reports have a many-to-many relationship.
The Problem
Django does not create a corresponding table to handle this relationship. My application is called reports. There is an error in the admin system upon trying to create a report and assign users to it. It tries to query the table reports_report_users and it fails as it does not exist.
models.py code
from django.db import models
from django.contrib.auth.models import User
class Report(models.Model):
name = models.CharField(max_length=30, blank=False)
users = models.ManyToManyField(User, related_name='reports')
def __unicode__(self):
return self.name
Attempted Solutions
Used this link as a reference: https://docs.djangoproject.com/en/1.4/topics/db/examples/many_to_many/
Ran manage.py syncdb about 300 times - ok, only once, but there were no errors and upon inspecting the SQLite db there were no additional tables created :(
It seems like you've added to the Report model after the first sync. Thus you're dealing with a migration, which django doesn't do natively.
First, Inspect the sql output, make sure that the create table instruction for your many to many relationship is there.
python manage.py sqlall
Assuming the problem is that this is a migration, which django doesn't handle natively, you've got three options:
1) Delete all db tables for this app, then run syncdb again.
2) Manually create the tables (fairly easy to copy paste the create sql from the sqlall command)
3) Start using a migration framework like South.
In the long run you'll appreciate the investment in learning south. In the short term, deleting the DB file is the fastest.-
Have you deleted your db file and run manage.py syncdb again?

Categories

Resources