ModelFormにおけるユニークフィールドのバリデーション

455 views
Skip to first unread message

xjr1300.04

unread,
Oct 23, 2008, 4:52:44 AM10/23/08
to django-ja
こんにちは、石黒と申します。

CentOS5.2 Python2.5.2 Django1.0 PostgreSQL8.2の環境で作成しています。
ユニークなフィールドを持つモデルのインスタンスを、ModelFormを使用して更新する方法で悩んでいます。

・モデルの抜粋
class Company(models.Model):
code = models.CharField(max_length = 4, unique = True) # 会社コード
name = models.CharField(max_length = 100, unique = True)
valid_from = models.DateField(default = date.today())
valid_to = models.DateField(default = date(9999, 12, 31))
update_datetime = models.DateTimeField(auto_now = True)

・フォームの抜粋
class CompanyForm(ModelForm):
code = forms.CharField(label = u'会社コード', widget =
forms.TextInput(attrs = {'size': '10'}), required = True)
name = forms.CharField(label = u'会社名', widget =
forms.TextInput(attrs = {'size': '60'}), required = True)
valid_from = forms.DateField(label = u'有効期間(開始)', widget =
AdminDateWidget, required = True)
valid_to = forms.DateField(label = u'有効期間(終了)', widget =
AdminDateWidget, required = True)
def __init__(self, *args, **kwargs):
super(CompanyForm, self).__init__(*args, **kwargs)
class Meta:
model = Company
def clean_code(self):
cleaned_code = self.cleaned_data['code']
if not cleaned_code.isdigit():
raise forms.ValidationError(u'会社コードには数字文字を入力してください。')
return cleaned_code
def clean(self):
cleaned = super(CompanyForm, self).clean()
date_from = cleaned.get('valid_from')
date_to = cleaned.get('valid_to')
if date_from is not None and date_to is not None:
if date_to < date_from:
raise forms.ValidationError(u'有効期間の終了日が開始日よりも前の日付です。')
return cleaned

上記コードで、既存のCompanyインスタンスのユニークなフィールドであるcodeを変更せずに更新しようとする
と、当然(?)ですがユニーク制約に関するエラーがModelFormのバリデーションで発生します。

ModelFormのcodeフィールドのデフォルトのバリデーションを、更新中のインスタンスと同じcodeを持つ他のイ
ンスタンスが存在するかどうかチェックするように変更するには、どこにチェックするコードを記述すればいい
のでしょうか?
Djangoにおける定石のようなものがあるのでしょうか?

例えば、idが1でcodeが'0001'の会社を編集して、idとcodeを変更せずに更新しようとしたときに、
Company.objects.filter(code__exact = '0001').exclude(id__exact = 1)が空の
QuerySetを返却すればバリデ
ーションに成功するようにしたいです。

以上、よろしくお願いします。長文で申し訳ありません。

xjr1300.04

unread,
Oct 23, 2008, 5:36:32 AM10/23/08
to django-ja
こんにちは、石黒と申します。

大いなる勘違いをしていました。原因はビューのほうにあったようです。

ビューでフォームからインスタンスを新しいインスタンスとして取得しているコードを
記述していました。
下記のように変更したところユニーク制約に関するエラーは報告されず、正常に更新できました。

Djangoを最近勉強しはじめたので、まだ勘違いしているかもしれませんが...。

def company_detail(request, id):
template = loader.get_template(u'organization/
organization_company_form.html')
context = RequestContext(request, None, [base_processor,])
company = get_object_or_404(Company, pk = id)
if request.method == 'POST':
form = CompanyForm(request.POST, instance = company)
if form.is_valid():
company = form.save()
redirect_url = '/django_site/organization/company/'
return HttpResponseRedirect(redirect_url)
else:
form = CompanyForm(instance = company)
context['form'] = form
context['verbose_name'] =
ContentType.objects.get_for_model(Company).name
return HttpResponse(template.render(context))

このような間違いをおこさないようにジェネリックビューを使用したほうがよさそうです。
Reply all
Reply to author
Forward
0 new messages