I have found in internet different examples on how to handle m2m relations with existing DB models, such as ex1 or here ex2, however I'm still not able to solve the error I get.
My models are depicted below. Basically, all the tables where created manually.
I got the following error message:
OperationalError: (1054, "Unknown column 'supervisor_project.id' in 'field list'").
I'm still a bit confused on when to use unique_together with through. Do you see any errors in the model below? The table supervisor_project has no id field and its PK is composed actually of two FK's, i.e. surrogate PK.
class Supervisor(models.Model):
name = models.CharField(max_length=45, blank=True, null=True, help_text="Name, e.g. John Smith")
class Meta:
managed = False
db_table = 'supervisor'
def __unicode__(self):
return self.name
class Project(models.Model):
title = models.CharField(max_length=45, blank=True, null=True)
supervisors = models.ManyToManyField(Supervisor, through='SupervisorProject', through_fields=('project', 'supervisor'))
class SupervisorProject(models.Model):
supervisor = models.ForeignKey('Supervisor', on_delete=models.CASCADE)
project = models.ForeignKey('Project', on_delete=models.CASCADE)
class Meta:
managed = False
db_table = 'supervisor_project'
unique_together = (('supervisor', 'project'),)
Django requires each model to have exactly one primary key field. It doesn't support multiple-column primary keys yet.
Since you haven't explicitly defined a primary key on the SupervisorProject model, Django assumes that there is an automatic primary key field id. When it includes the id field in a query, you get the error because it doesn't exist.
If possible, I would add an auto-incrementing id column to each intermediate table. There isn't a way to get Django to add the column to the tables automatically. You have set managed=False, so Django expects you to manage the database table.
Related
I am preparing tables for use in an analytics tool (Microsof Power BI).
It would be helpful to show relationships between the tables to assist in report building.
However, I don't want to use foreign keys with constraints because the method of data updating and integrity checking doesn't need constraints, and it will actually get in the way. Some of the alternate backends this code supports are for cloud databases that don't offer real foreign keys.
I mention that because it means I am trying to define a foreignkey field like this:
order_guid = models.ForeignKey("Dear_sales_header",to_field="order_guid",db_constraint=False,on_delete=models.DO_NOTHING)
The migration file has this:
operations = [
migrations.AlterField(
model_name='sales_fact',
name='order_guid',
field=models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.DO_NOTHING, to='dear_zoho_analytics.Dear_sales_header', to_field='order_guid'),
),
]
This table is routed to a different database
python manage.py migrate --database=dear_analytics
does indicate that the migration file was applied (it is 0026)
Applying dear_zoho_analytics.0026_auto_20210217_2245... OK
But when I inspect the postgresql schema in my IDE, the column in sales_fact is renamed to
order_guid_id
so it looks like I have done something wrong because this seems to reference the id field of the "parent table" dear_sales_header yet I need it to refer to dear_sales_header.order_guid which is unique but not the primary key.
Partial extract of Models:
class AnalyticsTable:
# a dummy class used to mark the DearAnalytics tables. Creating a subclass of models.Model breaks things in the ORM such as bulk update
pass
class Sales_fact(models.Model, AnalyticsTable):
analytics_table_name = "sales_fact"
#order_guid = models.CharField(max_length=1024, null=True, blank=True, help_text="")
order_guid = models.ForeignKey("Dear_sales_header",to_field="order_guid",db_constraint=False,on_delete=models.DO_NOTHING)
source_dear = models.CharField(max_length=1024, null=True, blank=True,
help_text="Link to Dear instance which is the source of the data")
class Dear_sales_header(models.Model, AnalyticsTable):
analytics_table_name = "dear_sales_header"
source_dear = models.CharField(max_length=1024, null=True, blank=True,
help_text="Link to Dear instance which is the source of the data")
order_guid = models.CharField(max_length=1024, unique=True, help_text="")
global_sale_status = models.CharField(max_length=1024, null=True, blank=True, help_text="SO Header status")
order_status = models.CharField(max_length=1024, null=True, blank=True, help_text="")
Django adds suffix _id to ForeignKey name as documented
Behind the scenes, Django appends "_id" to the field name to create
its database column name.
If you want name not to include any additions you should set db_column
The name of the database column to use for this field. If this isn’t
given, Django will use the field’s name.
order_guid = models.ForeignKey(
"Dear_sales_header", to_field="order_guid", db_constraint=False,
db_column='order_guid',on_delete=models.DO_NOTHING
)
In MRE I am not able to reproduce any undesired behavior,
Django does properly map ForeignKey to column you set also when settingdb_constraint=True properly ads back right constraint and drops it as backward operation
constraint testbench_sales_fact_order_guid_f2dab1c5_fk_testbench
references testbench_dear_sales_header (order_guid)
deferrable initially deferred
This is the error that I get when I try to update the value in the "parent" table that the foreign key is looking at in a related table:
ERROR: update or delete on table "product" violates foreign key constraint "pd_family_product_guid_ada83db3_fk_product_guid" on table "pd_family"
DETAIL: Key (guid)=(902d30b8-26ba-ea11-a812-000d3a5bbb60) is still referenced from table "pd_family".
SQL state: 23503
This is what I have for my models:
class Product(models.Model):
guid = models.UUIDField(primary_key=True)
product = models.CharField(max_length=10)
year = models.IntegerField()
previous_product_name = models.CharField(max_length=10)
class StandardProductFieldsMixin(models.Model):
product_guid = models.ForeignKey('Product', on_delete=models.CASCADE, db_column='product_guid')
class Meta:
abstract = True
class ActiveFieldMixin(models.Model):
active = models.BooleanField()
class Meta:
abstract = True
class Family(StandardProductFieldsMixin, ActiveFieldMixin):
new_code = models.IntegerField(null=True)
code = models.DecimalField(max_digits=20, decimal_places=2)
title = models.CharField(max_length=255)
desc = models.TextField(null=True)
fam_desc = models.TextField(null=True)
When I try to change a value of guid in Product, my expectation is that it would automatically change it in Family as well. I'm trying to change it with something like:
UPDATE product
SET guid = '902D30B8-26BA-EA11-A812-000D3A5BBB6B'
WHERE guid = '902D30B8-26BA-EA11-A812-000D3A5BBB60'
I guess I was under the wrong impression. Do I need to do something additional in the model? Looked at the documentation for something like on_update, but not seeing that either an **options or as a parameter for models.ForeignKey.
From what I gather after reading about it for more than an hour, if I want this kind of functionality I just need to add it Postgres manual, by dropping the constraint and adding it back with ON UPDATE CASCADE.
Apparently I'm under the wrong impression:
https://stackoverflow.com/a/61648910/3123109
Sounds like Django model migrations implement neither ON DELETE nor ON UPDATE database CASCADES options. I guess I'd need to drop into the database and implement them there.
I've a model as shown below:
class Instance(models.Model):
data_version = models.IntegerField(default=1, unique=True)
name = models.CharField(max_length=200)
The data_version field has to be related to all other models in the application:
class Source(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
version = models.ForeignKey(Instance, on_delete=models.CASCADE, to_field='data_version', null=True)
The problem here is that Django requires the field data_version to be a unique field for me to be able to define such a relationship but that simply doesn't fit into my use case. I need to have multiple Instance objects in the app, each with version numbers starting from 1.
What I'd like is to have a unique constraint on the combination of name and data_version but then Django doesn't allow defining Foreign key relationships as shown above. Is there a way I can bypass this restriction?
There are many similar questions on Stackoverflow, but none of the answers has helped me.
So, when running migrations, Django throws this error:
django.db.utils.ProgrammingError: there is no unique constraint matching given keys for referenced table "catalogues_movieslist"
I have this BlackWhiteCartoon model I am trying to create with the migration:
class BlackWhiteCartoon(BaseMovie, BaseList):
authors = JSONField(default=list, blank=True, null=True)
publisher = CharField(max_length=250, blank=True)
year = PositiveSmallIntegerField(blank=True, null=True)
This model inherits from the BaseList model that has only one field, a foreign key:
class BaseList(Model):
belongs_to_movies_list = ForeignKey(MoviesList, on_delete=CASCADE, null=True)
class Meta:
abstract = True
The referenced MoviesList model is the following:
class MoviesList(Model):
creation_date = DateTimeField(auto_now_add=True)
id = AutoField(primary_key=True)
uid = UUIDField(default=uuid.uuid4, editable=False)
user = ForeignKey(User, on_delete=CASCADE, null=True, blank=True)
Also, the BaseMovie model is the following:
class BaseMovie(BaseObject):
language = CharField(max_length=2, blank=True)
note = CharField(max_length=700, blank=True)
class Meta:
abstract = True
And the BaseObject model:
class BaseObject(Model):
id = BigAutoField(primary_key=True)
uid = UUIDField(default=uuid.uuid4, editable=False, db_index=True)
date_added = DateTimeField(null=True)
class Meta:
abstract = True
So, what I have tried:
Migrating everything together: this throws the above error.
Migrating BlackWhiteCartoon without inheriting BaseList first. This migration applies, but as soon as I add BaseList, it crashes with the same error.
Adding unique=True to the id field of MoviesList (both together with all other migrations and before adding BaseList to BlackWhiteCartoon). It throws the same error.
Adding to_field='id' together with 'unique=True'. The same error.
I have manually cleared the latest migrations from django_migrations in PSQL and removed the BlackWhiteCartoon table (to make sure that nothing prevents from migrating). To no avail either.
I have checked whether there are duplicated id's in the MoviesList table in the database. All id's are unique.
I have checked whether there are null foreign keys referencing to MoviesList in the database. There are none.
Also note that I have many models acting in absolutely the same way as BlackWhiteCartoon: Cartoon, Adventure, Action, etc. They are all functioning normally, yet they had been added several months ago.
Any ideas what I can do more?
I have database with many tables; three of those which are interlinked via primary and foreign keys are "Vendor_Details" , "Channel_Details" and "MSO_Details"
models.py
class Vendor_Details(models.Model):
class Meta:
verbose_name_plural = "Vendor_Details"
vendor_name = models.CharField(primary_key = True,max_length=50)
mso_id = models.CharField(unique = True, max_length=20)
class Channel_Details(models.Model):
class Meta:
verbose_name_plural = "Channel_Details"
channel_id = models.CharField(primary_key = True, max_length=20)
vendor_name = models.ForeignKey(Vendor_Details, on_delete=models.CASCADE)
channel_logo = models.CharField(max_length=50)
channel_name = models.CharField(max_length=50)
class MSO_Details(models.Model):
class Meta:
verbose_name_plural = "MSO_Details"
mso_id = models.ForeignKey(Vendor_Details, on_delete=models.CASCADE)
channel_id = models.ForeignKey(Channel_Details, on_delete=models.CASCADE)
channel_number = models.PositiveIntegerField()
So,
Channel_Details is linked to Vendor_Details with vendor_name and
MSO_Details is linked with Vendor_Details and Channel_Details with mso_id and channel_id respectively.
Now, I am inside Django's Administrator's MSO_Details table and trying to click on edit icon of CHANNEL ID column i get a new window opens with message Channel_ details with ID "CH6" doesn't exist. Perhaps it was deleted? May be this is because channel_id is primary key of reference table and DB will not allow the changes? But then the message should had been something different. How can i handle this situation? I clicked on edit for CH_006 and message shows CH6. I am confused whats going on here, what is django's DB refering to here?
Note : I can very well add new CHANNEL_DETAILS after click add button.
I had this kind problem for the last two days and the problem was
1. If on adding details to a new form initially, you do not add the right field required.(I was including both text and integers to a field that was only CharField)
2.The other solution when the error came again was to delete migrations and the database itself and create a new database again(Using the same database name).
In my case, I had an existing SQLite database that I've been migration over to Django. All my entities had a UUID column as their primary key.
I had set the primary key column as django.models.UUIDField thinking that Django would support it, but it doesn't.
So I converted it to a text field with UUID as default value, it started working again.
class Model(models.Model):
# id = models.UUIDField(primary_key=True)
id = models.TextField(primary_key=True, default=uuid.uuid4)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True