32

Is it possible to have a field in a Django model which does not get stored in the database.
For example:

class Book(models.Model):
    title = models.CharField(max_length=75)
    description models.CharField(max_length=255, blank=True)
    pages = models.IntegerField()
    none_db_field = ????

I could then do

book = Book.objects.get(pk=1)
book.none_db_field = 'some text...'
print book.none_db_field

Thanks

2
  • The code in the second part of your example could be run without setting none_db_field in the class. What are you trying to accomplish by having a field not stored in the database? Commented Feb 12, 2010 at 16:48
  • If the three lines are all you want to do, you don't need anything additional in the class Book. You can add anything to the book object and it only persists in its scope. Commented Feb 12, 2010 at 19:17

4 Answers 4

26

As long as you do not want the property to persist, I don't see why you can't create a property like you described. I actually do the same thing on certain models to determine which are editable.

class Email(EntryObj):
    ts = models.DateTimeField(auto_now_add=True)
    body = models.TextField(blank=True)
    user = models.ForeignKey(User, blank=True, null=True)
    editable = False
    ...


class Note(EntryObj):
    ts = models.DateTimeField(auto_now_add=True)
    note = models.TextField(blank=True)
    user = models.ForeignKey(User, blank=True, null=True)
    editable = True
Sign up to request clarification or add additional context in comments.

2 Comments

Now, when you call the save() method on an Email instance, it will also persist the editable field. How do I prevent it from persisting the editable field while persisting the rest?
Warning!! editable is a class variable if defined that way. You have to declare in __init__ method as stated in python doc (docs.python.org/3/tutorial/…)
17

Creating a property on the model will do this, but you won't be able to query on it.

Example:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

    def _get_full_name(self):
        return "%s %s" % (self.first_name, self.last_name)

    def _set_full_name(self, combined_name):
        self.first_name, self.last_name = combined_name.split(' ', 1)

    full_name = property(_get_full_name)

    full_name_2 = property(_get_full_name, _set_full_name)

Usage:

from mysite.models import Person

a = Person(first_name='John', last_name='Lennon')
a.save()
a.full_name
'John Lennon'

# The "full_name" property hasn't provided a "set" method.
a.full_name = 'Paul McCartney'
Traceback (most recent call last):
    ...
AttributeError: can't set attribute

# But "full_name_2" has, and it can be used to initialise the class.
a2 = Person(full_name_2 = 'Paul McCartney')
a2.save()
a2.first_name
'Paul'

2 Comments

Thanks for your answer. I've just tried this and it worked though. I added none_db_field = None to my model. I then tried: book.none_db_field = "testing" print book.none_db_field and it worked. Is this ok to do in Django?
Adding it to the model like that makes it a class attribute, which may or may not be what you want. Normally instance attributes are created in the __init__() method.
8

To make it an instance variable (so each instance gets its own copy), you'll want to do this

class Book(models.Model):
    title = models.CharField(max_length=75)
    #etc

    def __init__(self, *args, **kwargs):
        super(Foo, self).__init__(*args, **kwargs)
        self.editable = False

Each Book will now have an editable that wont be persisted to the database

Comments

1

If you want i18n support:

# Created by [email protected] at 2022/5/2
from typing import Optional

from django.db import models
from django.utils.translation import gettext_lazy as _


class Blog(models.Model):
    title = models.CharField(max_length=128, unique=True, verbose_name=_("Title"))
    content = models.TextField(verbose_name=_("Content"))
    _visitors: Optional[int] = None

    @property
    def visitors(self):
        return self._visitors

    @visitors.setter
    def visitors(self, value):
        self._visitors = value

    visitors.fget.short_description = _("Visitors")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.