Django Admin: OneToOne Relation as an Inline?

Viewed 44148

I'm putting together the admin for a satchmo application. Satchmo uses OneToOne relations to extend the base Product model, and I'd like to edit it all on one page.

Is it possible to have a OneToOne relation as an Inline? If not, what is the best way to add a few fields to a given page of my admin that will eventually be saved into the OneToOne relation?

for example:

class Product(models.Model):
    name = models.CharField(max_length=100)
    ...

class MyProduct(models.Model):
    product = models.OneToOne(Product)
    ...

I tried this for my admin but it does not work, and seems to expect a Foreign Key:

class ProductInline(admin.StackedInline):
    model = Product
    fields = ('name',)

class MyProductAdmin(admin.ModelAdmin):
    inlines = (AlbumProductInline,)

admin.site.register(MyProduct, MyProductAdmin)

Which throws this error: <class 'satchmo.product.models.Product'> has no ForeignKey to <class 'my_app.models.MyProduct'>

Is the only way to do this a Custom Form?

edit: Just tried the following code to add the fields directly... also does not work:

class AlbumAdmin(admin.ModelAdmin):
    fields = ('product__name',)
5 Answers

Referring to the last question, what would be the best solution for multiple sub-types. E.g class Product with sub-type class Book and sub-type class CD. The way shown here you would have to edit a product the general items plus the sub-type items for book AND the sub-type items for CD. So even if you only want to add a book you also get the fields for CD. If you add a sub-type e.g. DVD, you get three sub-type field groups, while you actually only want one sub-type group, in the mentioned example: books.

Jun, 2022 Update:

Yes, it's possible to have inline for one-to-one relation.

For example, as shown below, if "MyProduct" class has "models.OneToOneField()" referring to "Product" class which means "MyProduct" class has the ForeignKey referring to "Product" class:

# "models.py"

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)

class MyProduct(models.Model):
    name = models.CharField(max_length=100)
    product = models.OneToOneField( # Here
        Product, 
        on_delete=models.CASCADE,
        primary_key=True
    )

Then, you can inline "MyProduct" class under "Product" class as shown below:

# "admin.py"

from django.contrib import admin
from .models import Product, MyProduct

class MyProductInline(admin.TabularInline):
    model = MyProduct

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = (MyProductInline, )

Oppositely, as shown below, if "Product" class has "models.OneToOneField()" referring to "MyProduct" class which means "Product" class has the ForeignKey referring to "MyProduct" class:

# "models.py"

from django.db import models

class MyProduct(models.Model):
    name = models.CharField(max_length=100)

class Product(models.Model):
    name = models.CharField(max_length=100)
    my_product = models.OneToOneField( # Here
        MyProduct, 
        on_delete=models.CASCADE,
        primary_key=True
    )

Then, you can inline "Product" class under "MyProduct" class as shown below:

# "admin.py"

from django.contrib import admin
from .models import Product, MyProduct

class ProductInline(admin.TabularInline):
    model = Product

@admin.register(MyProduct)
class MyProductAdmin(admin.ModelAdmin):
    inlines = (ProductInline, )
Related