Support for foreign keys or one-to-one relationships as the primary key of the table
See original GitHub issueIs 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:
- Created 3 years ago
- Comments:5 (1 by maintainers)
Fixed, sorry did not notice this issue before. BTW, tortoise is open source, every one can make it better.
@paris-ci I was very disappointed, but I compromised by using sqlalchemy. I don’t think there is a workaround at the moment.