将 UniqueConstraint 添加到 ManyToMany 字段
Adding a UniqueConstraint to a ManyToMany field
我想在我的数据库中添加一个限制条件,以便一份申请只能与一个职位空缺相关联。我不希望能够从 shell 或 django 管理页面进入,进入一个空缺和 select 一个已经与空缺相关联的应用程序。我想提出某种验证错误。但是我有点不确定我应该怎么做?
models.py
class Vacancy(models.Model):
CATEGORY_CHOICES = [
('ADMINISTRATION', 'Administration'),
('CONSULTING', 'Consulting'),
('ENGINEERING', 'Engineering'),
('FINANCE', 'Finance'),
('RETAIL', 'Retail'),
('SALES', 'Sales'),
]
employer = models.ForeignKey('Employer', on_delete=models.CASCADE)
job_title = models.CharField(max_length=35, default=None)
main_duties = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
person_spec = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
salary = models.PositiveIntegerField(default=None, validators=[
MinValueValidator(20000),
MaxValueValidator(99000)
])
city = models.CharField(choices=CITY_CHOICES, max_length=11, default=None)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=15, default=None)
max_applications = models.PositiveSmallIntegerField(blank=True, null=True)
deadline = models.DateField(default=None)
applications = models.ManyToManyField('Application', blank=True, related_name='submissions')
class Meta:
verbose_name_plural = 'vacancies'
constraints = [
models.UniqueConstraint(fields=['id', 'applications'], name="unique_application")
]
class Application(models.Model):
STAGES = [
('pre-selection', 'PRE-SELECTION'),
('shortlisted', 'SHORTLISTED'),
('rejected pre-interview', 'REJECTED PRE-INTERVIEW'),
('rejected post-interview', 'REJECTED POST-INTERVIEW'),
('successful', 'SUCCESSFUL')
]
candidate = models.ForeignKey('Candidate', on_delete=models.CASCADE)
job = models.ForeignKey('Vacancy', on_delete=models.CASCADE)
cv = models.CharField(max_length=60, default=None)
cover_letter = models.TextField(default=None, validators=[
MinLengthValidator(0),
MaxLengthValidator(2000)
])
submitted = models.DateTimeField(auto_now_add=True)
stage = models.CharField(choices=STAGES, max_length=25, default='pre-selection')
如您所见,我已将约束添加到 Vacancy 模型:
constraints = [
models.UniqueConstraint(fields=['id', 'applications'], name="unique_application")
]
但是当我执行 makemigrations
然后 migrate
时,我得到这个错误:
raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: NewVacancy has no field named 'applications'
我不清楚这是什么意思。
有什么想法吗?
听起来像是一对多关系。您可以使用 related_name=applications
而不是 ManyToManyField
:
移动到 Application
上的 ForeignKey
class Vacancy(models.Model):
CATEGORY_CHOICES = [
('ADMINISTRATION', 'Administration'),
('CONSULTING', 'Consulting'),
('ENGINEERING', 'Engineering'),
('FINANCE', 'Finance'),
('RETAIL', 'Retail'),
('SALES', 'Sales'),
]
employer = models.ForeignKey('Employer', on_delete=models.CASCADE)
job_title = models.CharField(max_length=35, default=None)
main_duties = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
person_spec = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
salary = models.PositiveIntegerField(default=None, validators=[
MinValueValidator(20000),
MaxValueValidator(99000)
])
city = models.CharField(choices=CITY_CHOICES, max_length=11, default=None)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=15, default=None)
max_applications = models.PositiveSmallIntegerField(blank=True, null=True)
deadline = models.DateField(default=None)
class Application(models.Model):
STAGES = [
('pre-selection', 'PRE-SELECTION'),
('shortlisted', 'SHORTLISTED'),
('rejected pre-interview', 'REJECTED PRE-INTERVIEW'),
('rejected post-interview', 'REJECTED POST-INTERVIEW'),
('successful', 'SUCCESSFUL')
]
candidate = models.ForeignKey('Candidate', on_delete=models.CASCADE)
job = models.ForeignKey('Vacancy', on_delete=models.CASCADE)
cv = models.CharField(max_length=60, default=None)
cover_letter = models.TextField(default=None, validators=[
MinLengthValidator(0),
MaxLengthValidator(2000)
])
submitted = models.DateTimeField(auto_now_add=True)
stage = models.CharField(choices=STAGES, max_length=25, default='pre-selection')
vacancy = models.ForeignKey(Vacancy, related_name='applications', on_delete=models.DO_NOTHING)
我想在我的数据库中添加一个限制条件,以便一份申请只能与一个职位空缺相关联。我不希望能够从 shell 或 django 管理页面进入,进入一个空缺和 select 一个已经与空缺相关联的应用程序。我想提出某种验证错误。但是我有点不确定我应该怎么做?
models.py
class Vacancy(models.Model):
CATEGORY_CHOICES = [
('ADMINISTRATION', 'Administration'),
('CONSULTING', 'Consulting'),
('ENGINEERING', 'Engineering'),
('FINANCE', 'Finance'),
('RETAIL', 'Retail'),
('SALES', 'Sales'),
]
employer = models.ForeignKey('Employer', on_delete=models.CASCADE)
job_title = models.CharField(max_length=35, default=None)
main_duties = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
person_spec = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
salary = models.PositiveIntegerField(default=None, validators=[
MinValueValidator(20000),
MaxValueValidator(99000)
])
city = models.CharField(choices=CITY_CHOICES, max_length=11, default=None)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=15, default=None)
max_applications = models.PositiveSmallIntegerField(blank=True, null=True)
deadline = models.DateField(default=None)
applications = models.ManyToManyField('Application', blank=True, related_name='submissions')
class Meta:
verbose_name_plural = 'vacancies'
constraints = [
models.UniqueConstraint(fields=['id', 'applications'], name="unique_application")
]
class Application(models.Model):
STAGES = [
('pre-selection', 'PRE-SELECTION'),
('shortlisted', 'SHORTLISTED'),
('rejected pre-interview', 'REJECTED PRE-INTERVIEW'),
('rejected post-interview', 'REJECTED POST-INTERVIEW'),
('successful', 'SUCCESSFUL')
]
candidate = models.ForeignKey('Candidate', on_delete=models.CASCADE)
job = models.ForeignKey('Vacancy', on_delete=models.CASCADE)
cv = models.CharField(max_length=60, default=None)
cover_letter = models.TextField(default=None, validators=[
MinLengthValidator(0),
MaxLengthValidator(2000)
])
submitted = models.DateTimeField(auto_now_add=True)
stage = models.CharField(choices=STAGES, max_length=25, default='pre-selection')
如您所见,我已将约束添加到 Vacancy 模型:
constraints = [
models.UniqueConstraint(fields=['id', 'applications'], name="unique_application")
]
但是当我执行 makemigrations
然后 migrate
时,我得到这个错误:
raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: NewVacancy has no field named 'applications'
我不清楚这是什么意思。
有什么想法吗?
听起来像是一对多关系。您可以使用 related_name=applications
而不是 ManyToManyField
:
Application
上的 ForeignKey
class Vacancy(models.Model):
CATEGORY_CHOICES = [
('ADMINISTRATION', 'Administration'),
('CONSULTING', 'Consulting'),
('ENGINEERING', 'Engineering'),
('FINANCE', 'Finance'),
('RETAIL', 'Retail'),
('SALES', 'Sales'),
]
employer = models.ForeignKey('Employer', on_delete=models.CASCADE)
job_title = models.CharField(max_length=35, default=None)
main_duties = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
person_spec = models.TextField(default=None, validators=[
MinLengthValidator(650),
MaxLengthValidator(2000)
])
salary = models.PositiveIntegerField(default=None, validators=[
MinValueValidator(20000),
MaxValueValidator(99000)
])
city = models.CharField(choices=CITY_CHOICES, max_length=11, default=None)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=15, default=None)
max_applications = models.PositiveSmallIntegerField(blank=True, null=True)
deadline = models.DateField(default=None)
class Application(models.Model):
STAGES = [
('pre-selection', 'PRE-SELECTION'),
('shortlisted', 'SHORTLISTED'),
('rejected pre-interview', 'REJECTED PRE-INTERVIEW'),
('rejected post-interview', 'REJECTED POST-INTERVIEW'),
('successful', 'SUCCESSFUL')
]
candidate = models.ForeignKey('Candidate', on_delete=models.CASCADE)
job = models.ForeignKey('Vacancy', on_delete=models.CASCADE)
cv = models.CharField(max_length=60, default=None)
cover_letter = models.TextField(default=None, validators=[
MinLengthValidator(0),
MaxLengthValidator(2000)
])
submitted = models.DateTimeField(auto_now_add=True)
stage = models.CharField(choices=STAGES, max_length=25, default='pre-selection')
vacancy = models.ForeignKey(Vacancy, related_name='applications', on_delete=models.DO_NOTHING)