Почему я не могу сверлить модель, чтобы добраться до поля?
У меня есть эта модель участника:
class Contestant(models.Model):
GENDERS = [
("male", "Male"),
("female", "Female")
]
EYE_COLORS = [
("brown", "Brown"),
("blue", "Blue"),
("green", "Green"),
("hazel", "Hazel"),
("amber", "Amber"),
("gray", "Gray")
]
HAIR_COLORS = [
("black", "Black"),
("brown", "Brown"),
("blonde", "Blonde"),
("red", "Red"),
("gray", "Gray"),
("white", "White"),
("pink", "Pink"),
("purple", "Purple"),
("green", "Green"),
("orange", "Orange")
]
main_photo = models.FileField(upload_to='main_image/')
first_name = models.CharField(max_length=50)
middle_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=50)
date_of_birth = models.DateField()
gender = models.CharField(max_length=8, choices=GENDERS)
height = models.IntegerField(default=0,validators=[MinValueValidator(0), MaxValueValidator(120)])
weight = models.IntegerField(default=0,validators=[MinValueValidator(0), MaxValueValidator(1500)])
eye_color = models.CharField(max_length=20, choices=EYE_COLORS)
hair_color = models.CharField(max_length=20, choices=HAIR_COLORS)
city = models.OneToOneField(City, on_delete=models.DO_NOTHING, related_name="contestant")
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="contestant_profile")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")
class Meta:
verbose_name = "contestant"
verbose_name_plural = "contestants"
db_table = "contestants"
def __str__(self):
return f"contestant {self.user}"
и я хочу, чтобы люди проголосовали за участника. Вот модель голосования:
class ContestantVote(models.Model):
contestant = models.ForeignKey(Contestant, on_delete=models.CASCADE)
score = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(10)])
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="votes")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")
class Meta:
unique_together = (("contestant", "user"),)
verbose_name = "vote"
verbose_name_plural = "votes"
db_table = "votes"
def save(self, *args, **kwargs):
if ContestantVote.objects.filter(contestant=self.contestant, user=self.user).exists():
raise ValidationError(f'User {self.user} has already voted for contestant {self.contestant}.')
if self.score == 10:
existing_vote = ContestantVote.objects.filter(
user=self.user,
contestant__gender=self.contestant.gender,
score=10
).exists()
if existing_vote:
raise ValidationError(f'User {self.user} has already given a score of 10 to a {self.contestant.gender} contestant.')
super().save(*args, **kwargs)
def __str__(self):
return f"Vote for {self.contestant} by {self.user}"
Я пытаюсь запретить пользователю давать двум участницам одного пола одинаковый высший балл, равный 10, но постоянно сталкиваюсь с одной и той же ошибкой: поле не существует в голосовании, но я пытаюсь проверить поле в связанном поле, используя формат двойного подчеркивания.
Вот ошибка:
django.core.exceptions.FieldDoesNotExist: ContestantVote has no field named 'contestant__gender'
Может ли кто-нибудь сказать мне, что я делаю неправильно?
Похоже на проблему отсутствия/неприменения миграций.
В любом случае любой ответ, пытающийся назвать причину, не будет для вас полезным.
Вот что вам следует сделать:
- создайте унитесты
- создать тесты
- создать тесты
Есть много других вещей, которые вы могли бы улучшить, но они не помогут вам на данном этапе, но унитесты - это определенно первый шаг.
Добавьте тест на отсутствие миграций (в сети много ссылок на эту тему).
После добавления unittests:
- вернитесь к коду, где тесты пройдены
- добавьте нужный вам код
- тестируйте его, пока он не пройдет
- вернитесь к шагу 2.