question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support for foreign keys or one-to-one relationships as the primary key of the table

See original GitHub issue

Is your feature request related to a problem? Please describe. If the primary key of the table is a reference to another model, I cannot tell Tortoise about the relationship or certain functions will fail. Instead I have to define it as a regular Field type which does not allow me to use the relationship for prefetch_related or other joins.

Describe the solution you’d like If I define models such as these:

class Device(Model):
    device_id = CharField(pk=True, max_length=16)
    # ...

    status: ReverseRelation["DeviceStatus"]

class DeviceStatus(Model):
    device = OneToOneField('models.Device', pk=True, related_name='status')
    online = BooleanField(null=True)

I should be able to use code such as the following:

device_status = await DeviceStatus.get(device_id='SomeDeviceId')
device_status.online = True
await device_status.save()

Currently this produces an error,

  File "x.py", line 1049, in device_status
    await device_status.save()
  File ".../site-packages/tortoise/models.py", line 848, in save
    await executor.execute_update(self, update_fields)
  File ".../site-packages/tortoise/backends/base/executor.py", line 238, in execute_update
    values.append(self.model._meta.pk.to_db_value(instance.pk, instance))
  File ".../site-packages/tortoise/fields/base.py", line 179, in to_db_value
    if value is None or isinstance(value, self.field_type):
TypeError: isinstance() arg 2 must be a type or tuple of types

because the OneToOneField does not have a field_type set.

Describe alternatives you’ve considered By defining the models like this:

class Device(Model):
    device_id = CharField(pk=True, max_length=16)
    # ...

class DeviceStatus(Model):
    device_id = CharField(pk=True, max_length=16)
    online = BooleanField(null=True)

The .save() code above can be used, but you cannot access the relations e.g. device.status.

I think to make this work correctly, it would need to be possible to specify the field type of the OneToOneField or it would need to use the pk type of the target model for the field_type of the OneToOneField (or ForeignKeyField).

Additional context Not 100% sure if this would be considered a bug or a new feature, but since the documentation seems to imply that “pk” is not a valid kwarg for ForeignKeyField or OneToOneField and that those field types are not recommended for primary key types, I am assuming that it’s not intended to be supported. However, I do note that one of the models in the unit tests uses a primary key OneToOneField.

class Address(Model):
    city = fields.CharField(max_length=64)
    street = fields.CharField(max_length=128)

    event: fields.OneToOneRelation[Event] = fields.OneToOneField(
        "models.Event", on_delete=fields.CASCADE, related_name="address", pk=True
    )

I am also not sure if the issue is caused by or complicated by the primary key being a CharField rather than an IntField.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
long2icecommented, Jun 4, 2021

Fixed, sorry did not notice this issue before. BTW, tortoise is open source, every one can make it better.

0reactions
YutaUracommented, Jun 3, 2021

@paris-ci I was very disappointed, but I compromised by using sqlalchemy. I don’t think there is a workaround at the moment.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Which way should a Foreign Key go in a one to one relationship
If the 1-to-1 relationship between the two tables is identifying (the foreign key becomes the child's primary key), an identical data structure ...
Read more >
In a one-to-one relationship, where should the foreign key be ...
They can then be populated as required and defined as Foreign Keys. UserName is the Primary Key for the Users table. Use the...
Read more >
Understanding MySQL Foreign Keys - LogicalRead
Primary keys serve as unique identifiers for the records in a table, while foreign keys are used to link related tables together.
Read more >
Why Do Relational Databases Use Primary Keys and Foreign ...
A foreign key creates a link between two tables. It maintains referential integrity between the referencing column(s) and the referenced column( ...
Read more >
How To Implement One to One, One to Many and ... - Medium
... table and vice versa,we say that is a one to one relationship. This relationship can be created using Primary key-Unique foreign key…...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found