user7474631
user7474631

Reputation:

Set conditions to a field in Django Model

This is my Models:

class UserModel(models.Model):
    name = models.CharField(max_length=200)
    role = models.CharField(max_length=200)

class TestModel(models.Model):
    field1 = models.TextField()
    field2 = models.TextField()
    owner = models.ForeinkeyField(UserModel, on_delete=models.CASCADE)

Let the role field can have values role1, role2, and role3

and I want to restrict the TestModel having owner with role=role3

Upvotes: 0

Views: 921

Answers (2)

dirkgroten
dirkgroten

Reputation: 20692

You can set the choices option on model fields to limit the options available to a user (it changes the form field's widget from a TextInput widget to a Select widget). Note that this adds validation for these values when cleaning the model, it doesn't enforce this at the database level. It works when you use a ModelForm and then run is_valid() on the form for example.

And you can set the limit_choices_to option for ForeignKey fields. This will restrict the choices offered to the user in the corresponding form field when creating a ModelForm. Again, this is not enforced at database level, and it does not add any validation to the model. You'll have to add your own validation either on the form or on the model, e.g. by overriding the model's clean method or by overriding the model form's clean_owner method.

So on your model, you could do this:

def clean(self):
    if self.owner and not self.owner.role == 'role3':
        raise ValidationError({'owner': 'Owner must have role3'}, code='invalid')

Upvotes: 1

Ozgur Akcali
Ozgur Akcali

Reputation: 5492

To restrict possible values for role field;

class UserModel(models.Model):
    ROLE_CHOICES = (
        ('role1', 'Role 1'),
        ('role2', 'Role 2'),
        ('role3', 'Role 3'),
    )

    name = models.CharField(max_length=200)
    role = models.CharField(max_length=200, choices=ROLE_CHOICES)

To restrict TestModel owners to role3, I don't think there is a way to force it on the database level, but If you're using Django Rest Framework, you can force it on the application level by writing a custom permission class to the view that is responsible for creating TestModel entries to let only users with role3 be the owner for an instance of a TestModel. It would look like this:

class TestModelPermissions(permissions.BasePermission):
    def has_permission(self, request, view):
        if view.action == 'create':
            return request.user.role == 'role3'

        return True

Upvotes: 0

Related Questions