0

I am using django-solo to create a model which can have only one instance of it type. https://github.com/lazybird/django-solo

I have a model like this

class ProductPropertiesPriority(SingletonModel):
    product_type = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=1)
    style = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=2)
    color = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=3)
    series = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=4)
    size = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=5)
    brand = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
    default=6)

Here I want to set a priority to each field. I want all IntegerField in a single instance to be unique with each other. The value of one field shouldnot match with any other.

How can i solve this. Please help.

wrufesh
  • 1,379
  • 3
  • 18
  • 36

2 Answers2

1

You need to define unique_together in the Meta class of your model.

Sets of field names that, taken together, must be unique.

class ProductPropertiesPriority(SingletonModel):
    ...

    class Meta:
        # set of fields that must be unique together
        unique_together = (('product_type', 'style', 'color', `series`, `size`, 'brand'),)

Django will ensure that the tuple of tuple defined in unique_together option must be unique when considered together. It will be used in the Django admin and is enforced at the database level.

EDIT:

The above method will ensure uniqueness among different instances of the model. To ensure the uniqueness among different fields for a particular model instance, you will need to perform model validation.

You can do that by overriding the .clean() method in your model and write your validations there.

Here, in the clean() method, we will get the values of the fields and compare if they are distinct or not. If they are not distinct, then we will raise a validation error. Also, we override the .save() in the model and call the .full_clean() method as this method will call .clean() and few other methods also.

from django.core.exceptions import ValidationError

class ProductPropertiesPriority(SingletonModel):
    ...

    def clean(self, *args, **kwargs):
        """
        Write your custom validation to check for unique values here
        """
        my_unique_fields = ['product_type', 'style', 'color', 'series', 'size', 'brand']
        values = []
        for field in my_unique_fields:
            values.append(getattr(self, field))
        if len(values) != len(my_unique_fields):
            raise ValidationError(_('All the values must be distinct.'))
        super(ProductPropertiesPriority, self).clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.full_clean() # call the full_clean() method
        super(ProductPropertiesPriority, self).save(*args, **kwargs)

NOTE: Django, by default does not call the full_clean() method when save() is called (Check this SO link for more details). You will have to call this method yourself.

Community
  • 1
  • 1
Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
  • uniqie_together ensures uniqueness among two or more instance. I am talking about unique number amoung fields in a single instance. For me right now its not working. – wrufesh Sep 01 '15 at 15:50
  • Are you using a form to get the data and save the object? – Rahul Gupta Sep 01 '15 at 16:17
  • No I am not using get and post. Please see this for a moment https://github.com/lazybird/django-solo. We can directly register model to admin. – wrufesh Sep 01 '15 at 18:27
  • Sorry for replying late. Seems like i misunderstood your question. I have updated my ans so as to perform model validation before saving. This will check for uniqueness among the fields for a single instance. Please check it. – Rahul Gupta Sep 06 '15 at 08:09
0

One way would be to override clean() in your model, check the fields in this and raise validation error if two or more of them are same.

I can't say if this is the best way.

Saurabh Goyal
  • 605
  • 4
  • 21