2017-01-25 3 views
1

Учитывая эти две модели:ограничение Добавить к модели

models.py

PRIMARY, SECONDARY = 0, 1 
STORAGE_TYPE = (
    (PRIMARY, "Primary"), 
    (SECONDARY, "Secondary"), 
) 


class Storage(models.Model): 
    company = models.ForeignKey(Company, related_name='storage') 
    storage_type = models.PositiveIntegerField(choices=STORAGE_TYPE) 

class Company(models.Model): 
    name = models.CharField(max_length=64) 

Я хочу добавить ограничение поэтому одна компания только может иметь один первичный storage_type. Остальные должны быть вторичными.

Что было бы лучшим способом достичь этого?

Это хорошая практика ?:

models.py

# ... Storage model 

def clean(self): 
    if self.storage_type == PRIMARY: 
     if self.objects.filter(company=self.company, storage_type=PRIMARY).exists(): 
      raise ValidationError({'storage_type': 'Already exists a Primary storage.'}) 

ответ

1

Ну, это хорошая практика, если вы на базе данных, которая не поддерживает ограничений. Например, postgresql может выполнять такую ​​проверку на уровне базы данных. Всегда лучше полагаться на базу данных для обеспечения целостности данных там, где это возможно. Это потому, что вид проверки, который вы делаете в своем чистом методе, может привести к условиям гонки.

Если вы находитесь на чем-то вроде mysql (который имеет только уникальные и внешние ограничения ключа), вы можете продолжить свой текущий подход. Вы также можете рассмотреть возможность хранения чисел (1,2,3,) в вашем поле, так что 1 означает первичный, а 2,3,4 и т. Д. Означает вторичные хранилища. Таким образом, вы также можете дать им порядок приоритета. Затем:

class Storage(models.Model): 
    company = models.ForeignKey(Company, related_name='storage') 
    storage_type = models.PositiveIntegerField(choices=STORAGE_TYPE) 

    class Meta: 
     unique_together = ('company','storage') 
0

Вы должны выполнить эту задачу в виде метода сохранения.

forms.py

class StorageForm(forms.ModelForm): 
    def clean_company(self): 
     company = self.cleaned_data.get('company') 
     if company.storage_set.filter(storage_type=0).exists(): 
      raise forms.ValidationError('your_message') 
     return company 

    class Meta: 
     model = Storage 
     fields = '__all__' 
Смежные вопросы