Najaaz
Najaaz

Reputation: 390

Two OneToOneFields for the same table are not allowed in Django models

so I am trying to store the user's location coordinates in another table by linking it to the original using a OneToOneField.

class Coordinates(models.Model):
    lat = models.FloatField()
    lng = models.FloatField()


class Trip (models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True) #Drivers Profile
    departure = models.CharField(max_length=200)
    departureCoord = models.OneToOneField(Coordinates, on_delete=models.PROTECT)
    arrival = models.CharField(max_length=200)
    arrivalCoord = models.OneToOneField(Coordinates, on_delete=models.PROTECT)
    date = models.DateField(validators=[inthe_future])
    time = models.TimeField(default=datetime.now().time())
    vacant_seats = models.PositiveIntegerField()
    vehicle_used = models.ForeignKey(Vehicle, on_delete=models.PROTECT)
    price_per_person = models.IntegerField()
    status = models.CharField(choices=STATUS, default='UPCOMING', max_length=10)

    def __str__ (self):
        return f"{self.user.first_name} - ({self.departure} => {self.arrival})"

I have used an OneToOneField for both arrivalCoord and departureCoord since each row on the Coordinates table is going to uniquely link the departure and arrival of every Trip.

So by still having a one-to-one relationship, is it possible for me to get the same thing done as when I try to run makemigrations I'm thrown with this error.

←[31;1mapp.Trip.departureCoord: (fields.E304) Reverse accessor for 'app.Trip.departureCoord' clashes with reverse accessor for 'app.Trip.arrivalCoord'.
        HINT: Add or change a related_name argument to the definition for 'app.Trip.departureCoord' or 'app.Trip.arrivalCoord'.←[0m
←[31;1mapp.Trip.departureCoord: (fields.E305) Reverse query name for 'app.Trip.departureCoord' clashes with reverse query name for 'app.Trip.arrivalCoord'.
        HINT: Add or change a related_name argument to the definition for 'app.Trip.departureCoord' or 'app.Trip.arrivalCoord'.←[0m

I think there is a better way to improve the design of the database, are you'll aware of anything?

Thanks!

EDIT

This is my latest migration file...

# Generated by Django 3.2.3 on 2021-06-18 04:22

import datetime
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

    dependencies = [
        ('app', '0020_alter_trip_time'),
    ]

    operations = [
        migrations.CreateModel(
            name='Coordinates',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('lat', models.FloatField()),
                ('lng', models.FloatField()),
            ],
        ),
        migrations.AlterField(
            model_name='trip',
            name='time',
            field=models.TimeField(default=datetime.time(9, 52, 22, 413173)),
        ),
        migrations.AddField(
            model_name='trip',
            name='arrivalCoord',
            field=models.OneToOneField(default=0.0, on_delete=django.db.models.deletion.PROTECT, related_name='arrivalCoord', to='app.coordinates'),
        ),
        migrations.AddField(
            model_name='trip',
            name='departureCoord',
            field=models.OneToOneField(default=0.0, on_delete=django.db.models.deletion.PROTECT, related_name='departureCoord', to='app.coordinates'),
        ),
    ]

I have created the Coordinates table and the OneToOneField for the first time.

Upvotes: 1

Views: 486

Answers (1)

Iain Shelvington
Iain Shelvington

Reputation: 32274

You need to add a unique related_name to each OneToOneField so that unique reverse relationships can be added to the Coordinates model

class Trip (models.Model):
    ...
    departureCoord = models.OneToOneField(Coordinates, on_delete=models.PROTECT, related_name='departure')
    arrivalCoord = models.OneToOneField(Coordinates, on_delete=models.PROTECT, related_name='arrival')
    ...

Upvotes: 1

Related Questions