Уникальное ограничение Django + ошибки формы - PullRequest
4 голосов
/ 13 августа 2010

У меня проблемы с двойной публикацией на моем сайте.Я полагаю, что простое уникальное ограничение во всех соответствующих полях решит проблему на уровне базы данных, но затем просто создаст неприятную страницу с ошибкой для пользователя.Есть ли способ, которым я могу превратить это в красивую ошибку формы вместо?Как non_field_error?Или какой подход мне выбрать?

Ответы [ 2 ]

11 голосов
/ 13 августа 2010

Может быть, что-то вроде этого поможет вам:

class YourForm(forms.Form):
    # Everything as before.
    ...

    def clean(self):
        cleaned_data = self.cleaned_data
        your_unique_key = cleaned_data['your_unique_key']

        if your_unique_key and YourModel.objects.get(your_unique_key=your_unique_key):
            raise forms.ValidationError("not unique")

        # Always return the full collection of cleaned data.
        return cleaned_data

Метод clean() позволит вам получить доступ ко всем полям формы, которые могут быть полезны, если у вас есть комбинированный уникальный ключ.В противном случае (немного короче) clean_your_unique_key() может подойти вам лучше.

И, пожалуйста, обратите внимание, что при редких обстоятельствах (условиях гонки) проверка формы может не сообщать о повторяющейся записи (но это, конечно, сообщается ядром базы данных).Но для большинства приложений приведенный пример будет более простым и более легким в обслуживании, поэтому я все же рекомендую этот подход.

1 голос
/ 13 августа 2010

Насколько «страница с неприятными ошибками» для пользователя, Django позволяет вам настроить свои собственные 500,404 и, возможно, другие страницы. общая информация по этому вопросу:

Для использования исключения Http404 в полной мере, вы должны создать шаблон, который отображается при 404 ошибка повышена Этот шаблон должен называться 404.html и находится в верхний уровень вашего дерева шаблонов.

- http://docs.djangoproject.com/en/dev/topics/http/views/

Другим хорошим способом, не таким СУХИМЫМ, как решение tux21b, но, возможно, немного более понятным для одноразового решения, может быть интеллектуальное обнаружение ошибки. Одним из способов является сделать это, даже не потревожив нарушить ограничение - простой запрос должен проверить, собирается ли пользователь сделать что-то незаконное.

okToUpdate=MyModel.objects.filter(parameters=values...).count()  

if okToUpdate>0:  # an object already exists  
    errorExists=True  
    errors={customError:customMessage}  

...  

if errorExists:  
     return render_to_response(errors,'customErrorPage.html')  

else:  
    # return whatever you normally would return  

Затем вы используете render_to_response для визуализации пользовательской страницы ошибки.

(другой способ - допустить нарушение базы данных, затем перехватить эту ошибку и сделать то же самое ... я предполагаю, что при поиске БД получает немного меньше стресса, чем при обработке исключения, но вам решать, как вы нравится делать вещи).

JB

...