3

I am having a confusion on how to model a relationship in Django so that it can be edited inline in the Django Admin.

Let me explain the scenario.

I have a Customer Model and An Address Model. In the customer model I have a OneToOneField relationship to Address once for billing and once for shipping address.

class Address(models.Model):
    pass

class Employee(models.Model):
    billing_address = models.OneToOneField(Address)
    shipping_address = models.OneToOneField(Address)
    # Many more such fields

Now with this model there is no easy way to make them inline in Admin. I have tried the following

class AddressInline(admin.TabularInline):
    model = Address

class Customer(admin.ModelAdmin):
    inlines = [AddressInline, ]

I keep getting an error,

<class 'employee.admin.AddressInline'>: (admin.E202) 'employee.Address' has no ForeignKey to 'employee.Customer'.

Now I know there are other bugs similar to this one. ie. Use OneToOneField inlined in Django Admin and Django admin - OneToOneField inline throws "has no ForeignKey" exception

But I think my question is slightly different to warrant this post. Please help!

Community
  • 1
  • 1
vivekv
  • 2,238
  • 3
  • 23
  • 37

1 Answers1

2

#1

models.py

class BillingAddress(models.Model):
    employee = models.OneToOneField(to=Employee, related_name='billing_address')

class Employee(models.Model):
    # Many more such fields

admin.py

class AddressInline(admin.TabularInline):
    model = BillingAddress
    extra = 1

@admin.register(Employee)
class EmployeeAdmin(admin.ModelAdmin):
    inlines = [AddressInline, ]

#2

models.py

class Address(models.Model):
    name = models.CharField(max_length=250)
    employee = models.ForeignKey(to=Employee, related_name='addresses')

class Employee(models.Model):
    # Many more such fields

admin.py

class AddressInline(admin.TabularInline):
    model = Address

@admin.register(Employee)
class EmployeeAdmin(admin.ModelAdmin):
    inlines = [AddressInline, ]

Full Example:

models.py

class Company(models.Model):
    pass


class CompanyScheduler(models.Model):
    company = models.OneToOneField(
        to=Company,
        related_name='scheduling',
        on_delete=models.CASCADE,
    )

    start = models.DateField()
    finish = models.DateField()

admin.py

class CompanySchedulerInLine(admin.TabularInline):
    model = CompanySchedulerInLine
    extra = 1


@admin.register(CompanyModelAdmin)
class CompanyModelAdmin(admin.ModelAdmin):

    inlines = [
        SchedulerInLine,
    ]

UI

enter image description here

Sonic Park
  • 19
  • 4
  • The issue I am having is with one to one relationships in django. The examples you have given do not address that problem. – vivekv Feb 20 '21 at 12:36
  • The first example I gave solves the problem. All you need to do is either declare the relationship in the second model, not in the first, or use Inline in "AddressAdmin". Most likely you haven't even tried it) – Sonic Park Feb 20 '21 at 21:29
  • yes I saw your solution. You are changing the database design to accommodate django which is not an acceptable solution. When you see the database table the foreign key relationships are reversed which is not correct. – vivekv Feb 22 '21 at 11:56