Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I make at least one field a requirement on a Django Model?

Say I have a Person model:

class Person(models.Model):
    name = models.CharField(max_length=50)

    email = models.EmailField()
    telephone = models.CharField(max_length=50)

For every Person I want to ensure that there is contact information. I don't need both email and telephone (though both is okay) but I need to ensure that at least one is provided.

I know I can check this stuff in forms, but is there a way I can do this at Model/database level to save repeating myself?

like image 994
Oli Avatar asked Aug 05 '15 11:08

Oli


People also ask

How do you make a field not required in Django?

The simplest way is by using the field option blank=True (docs.djangoproject.com/en/dev/ref/models/fields/#blank).

How do I add a field to a Django model?

To answer your question, with the new migration introduced in Django 1.7, in order to add a new field to a model you can simply add that field to your model and initialize migrations with ./manage.py makemigrations and then run ./manage.py migrate and the new field will be added to your DB.

Is there a list field for Django models?

Mine is simpler to implement, and you can pass a list, dict, or anything that can be converted into json. In Django 1.10 and above, there's a new ArrayField field you can use.


1 Answers

Write a clean method for your model.

from django.core.exceptions import ValidationError


class Person(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()
    telephone = models.CharField(max_length=50)

    def clean(self):
        if not (self.email or self.telephone):
            raise ValidationError("You must specify either email or telephone")

If you use a model form (e.g. in the Django admin), Django will call the clean method for you. Alteratively, if you are using the ORM directly, you can call the full_clean() method on the instance manually.

like image 97
Alasdair Avatar answered Oct 18 '22 19:10

Alasdair