Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django empty field fallback

I have a model that holds user address. This model has to have first_name and last_name fields since one would like to set address to a recipient (like his company, etc.). What I'm trying to achieve is:

  • If the first_name/last_name field in the address is filled - return simply that field
  • If the first_name/last_name field in the address is empty - fetch the corrresponding field data from a foreignkey pointing to a proper django.auth.models.User
  • I'd like this to be treated as normal Django field that would be present in fields lookup
  • I don't want to create a method, since it's a refactoring and Address.first_name/last_name are used in various places in the application (also in model forms, etc.), so I need this to me as smooth as possible, or else, I will have to tinker around in a lot of places.
like image 475
pielgrzym Avatar asked Aug 27 '09 17:08

pielgrzym


People also ask

How do I make a field optional in Django?

You would have to add blank=True as well in field definition. If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True. Don't forget to reset and sync DB again after changing this.

How do I lock a field in Django?

select_for_update is the simplest way to acquire a lock on an object, provided your database supports it. PostgreSQL, Oracle, and MySQL, at least, support it, according to the Django docs. Note that you have to use select_for_update within a transaction, hence the @transaction. atomic decorator.

What is CharField in Django?

CharField is a commonly-defined field used as an attribute to reference a text-based database column when defining Model classes with the Django ORM. The Django project has wonderful documentation for CharField and all of the other column fields.

How do you make a field not required in Django?

Just add blank=True in your model field and it won't be required when you're using modelforms . "If the model field has blank=True , then required is set to False on the form field. Otherwise, required=True ."


1 Answers

There are two options here. The first is to create a method to look it up dynamically, but use the property decorator so that other code can still use straight attribute access.

class MyModel(models.Model):
    _first_name = models.CharField(max_length=100, db_column='first_name')

    @property
    def first_name(self):
        return self._first_name or self.user.first_name

    @first_name.setter
    def first_name(self, value):
       self._first_name = value

This will always refer to the latest value of first_name, even if the related User is changed. You can get/set the property exactly as you would an attribute: myinstance.first_name = 'daniel'

The other option is to override the model's save() method so that it does the lookup when you save:

def save(self, *args, **kwargs):
    if not self.first_name:
        self.first_name = self.user.first_name
    # now call the default save() method
    super(MyModel, self).save(*args, **kwargs)

This way you don't have to change your db, but it is only refreshed on save - so if the related User object is changed but this object isn't, it will refer to the old User value.

like image 84
Daniel Roseman Avatar answered Sep 23 '22 10:09

Daniel Roseman