2010-08-13 3 views
2

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

+0

Я бы очень хотел проголосовать за этот вопрос, если вы согласитесь с ответом. – raratiru

+0

@raratiru Хорошо, если это делает вас счастливым, я выбрал один;) Не уверен, что это фактическое решение, с которым я побывал 7 лет назад - я обычно принимаю тот, который я использую. – mpen

+0

Собственно, это тот, который я использовал! :-D – raratiru

ответ

8

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

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

насколько «неприятная страница ошибки» для пользователя, 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

+0

Ух .. .. вверх по странице 500 не улучшается. Они все еще убраны с страницы, на которой они должны быть, и действительно, это вводит в заблуждение, потому что на самом деле одно из их сообщений * * прошло, так что это не настоящая «ошибка», а предупреждение, если оно даже заслуживает того. Что касается вашего второго решения ... это не намного лучше. Это ломается СУХОЙ. Такая вещь должна действительно быть в форме, в том же месте, где происходит валидация. – mpen

+0

Я говорил вообще и, возможно, не к конкретному использованию форм джанго. вы описали результаты как «неприятную страницу ошибок». Вторая идея, разбивающая DRY, я прямо упоминаю, что это не СУХОЙ, а один таймер. Чтобы сделать многоразовым, вы можете инкапсулировать его в функцию, вызываемую из любого места. т.е. Защиту checkModelUpdateOk (anyModel, someParams, ...): okToUpdate = anyModel.complex_filter (someParams) .count() (и так далее, возвращая сообщение об ошибке или зеленый свет) ... с someParams - это dict, указывающий ключи и значения, которые вы ищете (для вашей предполагаемой модели). - j – jsh

+0

Число параметров почти равно длине кода :) Anywho, они действительные решения, просто не предпочтительные. – mpen

Смежные вопросы