简体   繁体   中英

Restricting database in Postgresql

I am using Django1.9 with Postgresql. This is my data model for the model "Feature" :

class Feature(models.Model):
    image_component = models.ForeignKey('Image_Component',on_delete=models.CASCADE,)
    feature_value = HStoreField()

    def save(self,*args,**kwargs):
        if Feature.objects.filter(feature_value__has_keys=['size', 'quality' , 'format']):
            super(Feature, self).save(*args, **kwargs)
        else:
            print("Incorrect key entered")

I am imposing a restriction on the feature_value such that only the keys that is allowed with Hstore are size , format and quality. I can do this while updating the database using Django-Admin. But I am not able to update the database directly using pgAdmin3 with the same restrictions ie , I want to impose the same restrictions on the database level. How can I do that? Any suggestions?

You need to ALTER you Future table and add a constraint for feature_value field with such query:

ALTER TABLE your_feature_table
ADD CONSTRAINT restricted_keys
CHECK (
  -- Check that 'feature_value' contains all specified keys
  feature_value::hstore ?& ARRAY['size', 'format', 'quality']
  AND
  -- and that number of keys is three
  array_length(akeys(feature_value), 1) = 3
);

This will ensure that every data in feature_value could contain exactly three keys: size, format and quality; and won't allow empty data.

Note, that before applying this query, you need to remove all invalid data from the table, or you would receive an error:

ERROR: check constraint "restricted_keys" is violated by some row

You could execute this query in DB console, or since you're using Django, it would be more appropriate to create a migration and apply this query using RunSQL : create an emtpy migration and pass above query into migrations.RunSQL , and pass this query into reverse_sql param for removing the constraint when the migration is unapplied:

ALTER TABLE your_feature_table
DROP CONSTRAINT restricted_keys;

After applying:

sql> INSERT INTO your_feature_table (feature_value) VALUES ('size => 124, quality => great, format => A4')
1 row affected in 18ms

sql> INSERT INTO your_feature_table (feature_value) VALUES ('format => A4')
ERROR: new row for relation "your_feature_table" violates check constraint "restricted_keys"
Detail: Failing row contains ("format"=>"A4").

sql> INSERT INTO your_feature_table (feature_value) VALUES ('')
ERROR: new row for relation "your_feature_table" violates check constraint "restricted_keys"
Detail: Failing row contains ().

sql> INSERT INTO your_feature_table (feature_value) VALUES ('a => 124, b => great, c => A4')
ERROR: new row for relation "your_feature_table" violates check constraint "restricted_keys"
Detail: Failing row contains ("a"=>"124", "b"=>"great", "c"=>"A4").

sql> INSERT INTO your_feature_table (feature_value) VALUES ('size => 124, quality => great, format => A4, incorrect_key => error')
ERROR: new row for relation "your_feature_table" violates check constraint "restricted_keys"
Detail: Failing row contains ("size"=>"124", "format"=>"A4", "quality"=>"great", "incorrect_ke...).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM