Проверка, не дублируется ли база данных с нулевым полем

#django #django-models #django-views

#django #django-модели #django-просмотры

Вопрос:

Я пытаюсь проверить, есть ли дублирующаяся запись в базе данных, прежде чем добавлять запись. Вот мои текущие модели —

 class Education(models.Model):
    school = models.CharField(max_length=100)
    class_year = models.IntegerField(max_length=4, blank=True, null=True, choices=YEAR)
    degree = models.CharField(max_length=100, blank=True, null=True)

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    employments = models.ManyToManyField(Employment)
  

В форме пользователь должен ввести школу. Год выпуска и степень необязательны. Чтобы проверить наличие дублирующихся записей, прямо сейчас у меня есть —

 if form.is_valid() and request.POST['school']:
    school = form.cleaned_data['school']
    try:
        school_object = Education.objects.get(school=form.cleaned_data['school'],
                                              class_year=form.cleaned_data['class_year'],
                                              degree = form.cleaned_data['degree'])
    except (Education.DoesNotExist):
        school_object = Education(school=form.cleaned_data['school'],
                                  class_year=form.cleaned_data['class_year'],
                                  degree = form.cleaned_data['degree'])
        school_object.save()
        profile.educations.add(school_object)
        profile.save()
  

Я получаю ошибку ValueError, если class_date не заполнен. Как это исправить, а также при проверке на наличие дубликатов? Спасибо.

Ответ №1:

Во-первых, если у вас нет веской причины, вам действительно не следует обращаться к переменным post без отправки их через форму.

 from django import forms
class MyForm(forms.form):
  school = forms.CharField()
  degree = forms.CharField(required=False)
  class_year = forms.CharField(required=False)

  def clean(self):
    if not self.cleaned_data.has_key('degree'):
      self.cleaned_data['degree'] = None
    if not self.cleaned_data.has_key('class_year'):
      self.cleaned_data['class_year'] = None
    return self.cleaned_data
  

Затем, когда вы обрабатываете представление:

 ...
if request.method == "POST":
  form = MyForm(request.POST)
  if form.is_valid():
    try:
      # NOTE that the objects.get method will raise MultipleObjectsReturned if the
      # database has more than one object that matches the query
      my_object = Education.objects.get(school=form.cleaned_data['school'], 
        class_year=form.cleaned_data['class_year'], 
        degree = form.cleaned_data['degree'])
    except Education.DoesNotExist:
      my_object = Education(school=form.cleaned_data['school'], 
        class_year=form.cleaned_data['class_year'], 
        degree = form.cleaned_data['degree'])
else:
  form = MyForm()
...
  

Комментарии:

1. Это не устраняет проблему наличия поля Null / None для class_year. Это все равно создаст ValueError для недопустимого литерала с базой 10(). Есть еще идеи?

2.Я изменил метод clean на следующий, который теперь работает: if not self.cleaned_data.get('class_year'): self.cleaned_data['class_year'] = None if not self.cleaned_data.get('degree'): self.cleaned_data['degree'] = '' return self.cleaned_data

Ответ №2:

В представлениях:

 if 'Add School' in request.POST.values():
    form = EducationForm(request.POST)
    if form.is_valid() and request.POST['school']:
        school = form.cleaned_data['school']
        try:
            school_object = Education.objects.get(school=form.cleaned_data['school'],
                                              class_year=form.cleaned_data['class_year'],
                                              degree = form.cleaned_data['degree'])
        except (Education.DoesNotExist, ValueError):
            school_object = Education(school=form.cleaned_data['school'],
                                              class_year=form.cleaned_data['class_year'],
                                              degree = form.cleaned_data['degree'])
            school_object.save()
            profile.educations.add(school_object)
            profile.save()
            return redirect('edit_education')
  

Или, используя get_or_create для упрощения:

 if 'Add School' in request.POST.values():
    form = EducationForm(request.POST)
    if form.is_valid() and request.POST['school']:
        school = form.cleaned_data['school']
        school_object, created = Education.objects.get_or_create(school=form.cleaned_data['school'],
                                          class_year=form.cleaned_data['class_year'],
                                          degree = form.cleaned_data['degree'])
        if created:
            profile.educations.add(school_object)
            profile.save()
            return redirect('edit_education')
  

В формах:

 YEAR = ([(x, x) for x in range(1970,2015)])
YEAR.append((0,'Select Year'))
YEAR.reverse()

class EducationForm(forms.Form):
    school = forms.CharField()
    class_year = forms.ChoiceField(choices=YEAR, required=False)
    degree = forms.CharField(required=False)
    def clean(self):
        if not self.cleaned_data.get('class_year'):
            self.cleaned_data['class_year'] = None
        if not self.cleaned_data.get('degree'):
            self.cleaned_data['degree'] = ''
        return self.cleaned_data