Search code examples
pythondjangoone-to-one

Accessing one-to-one table field value in Django


I have a Django model which creates a one-to-one-field relationship with Django sites

from django.contrib.sites.models import Site

class SiteSettings(models.Model):
    site = models.OneToOneField(Site, related_name="settings", on_delete=models.CASCADE)
    header_text = models.CharField(max_length=200, blank=True)

I want to access the header_text field in the SiteSettings table from the Site model. I have tried getting the value using:

value = Site.settings.header_text
print(value)

I get the error:

AttributeError: 'ReverseOneToOneDescriptor' object has no attribute 'header_text'

Any help is appreciated.


Solution

  • Site is a reference to the Site class, not a Site object. You can use get_current() [Django-doc] to obtain the current site and then use the relation in reverse:

    from django.contrib.sites.shortcuts import get_current_site
    
    get_current().settings.header_text

    If there are no multiple sites, it makes not much sense to work with a ForeignKey to Site in the first place, since there will only be one. In that case, you can make a model:

    # if there are no multiple Sites
    from django.db import models
    
    class SiteSettings(models.Model):
        # no ForeignKey to Site
        header_text = models.CharField(max_length=200, blank=True)

    then you make sure there is exactly one records for the SiteSettings, and you access it with:

    # if there are no multiple Sites and only one SiteSettings record
    SiteSettings.objects.get().header_text

    you can slighly boost the performance by using .only(…) [Django-doc]:

    # if there are no multiple Sites and only one SiteSettings record
    SiteSettings.objects.only('header_text').get().header_text