#django #django-models #django-forms #foreign-keys
#django #django-модели #django-forms #внешние ключи
Вопрос:
Что я хотел бы сделать, так это отобразить единственную форму, которая позволяет пользователю:
- Введите название документа (из
Document
модели) - Выберите один из их
user_defined_code
вариантов из выпадающего списка (заполняетсяUserDefinedCode
моделью) - Введите
unique_code
(сохраненное вCode
модели)
Я не уверен, как отобразить поля для отношений внешнего ключа в форме. Я знаю, что в представлении вы можете использовать document.code_set (например) для доступа к связанным объектам для текущего document
объекта, но я не уверен, как применить это к ModelForm.
Моя модель:
class UserDefinedCode(models.Model):
name = models.CharField(max_length=8)
owner = models.ForeignKey(User)
class Code(models.Model):
user_defined_code = models.ForeignKey(UserDefinedCode)
unique_code = models.CharField(max_length=15)
class Document(models.Model):
title = models.CharField(blank=True, null=True, max_length=200)
code = models.ForeignKey(Code)
active = models.BooleanField(default=True)
Моя форма модели
class DocumentForm(ModelForm):
class Meta:
model = Document
Ответ №1:
Что касается отображения поля внешнего ключа в форме, вы можете использовать forms.ModelChoiceField
и передать ему набор запросов.
итак, forms.py:
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
def __init__(self, *args, **kwargs):
user = kwargs.pop('user','')
super(DocumentForm, self).__init__(*args, **kwargs)
self.fields['user_defined_code']=forms.ModelChoiceField(queryset=UserDefinedCode.objects.filter(owner=user))
views.py:
def someview(request):
if request.method=='post':
form=DocumentForm(request.POST, user=request.user)
if form.is_valid():
selected_user_defined_code = form.cleaned_data.get('user_defined_code')
#do stuff here
else:
form=DocumentForm(user=request.user)
context = { 'form':form, }
return render_to_response('sometemplate.html', context,
context_instance=RequestContext(request))
из вашего вопроса:
Я знаю, что в представлении вы можете использовать document.code_set (например) для доступа к связанным объектам для текущего объекта document, но я не уверен, как применить это к ModelForm.
На самом деле, у ваших Document
объектов не было бы .code_set
, поскольку отношение FK определено в вашей модели documents. Оно определяет отношение «многие к одному» для Code
, что означает, что на Document
объект может приходиться много Code
объектов, а не наоборот. Ваши Code
объекты будут иметь .document_set
. Что вы можете сделать из объекта document, так это access, с Code
использованием которого это связано document.code
.
редактировать: Я думаю, это сделает то, что вы ищете. (непроверено)
forms.py:
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
exclude = ('code',)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user','')
super(DocumentForm, self).__init__(*args, **kwargs)
self.fields['user_defined_code']=forms.ModelChoiceField(queryset=UserDefinedCode.objects.filter(owner=user))
self.fields['unique_code']=forms.CharField(max_length=15)
views.py:
def someview(request):
if request.method=='post':
form=DocumentForm(request.POST, user=request.user)
if form.is_valid():
uniquecode = form.cleaned_data.get('unique_code')
user_defined_code = form.cleaned_data.get('user_defined_code')
doc_code = Code(user_defined_code=user_defined_code, code=uniquecode)
doc_code.save()
doc = form.save(commit=False)
doc.code = doc_code
doc.save()
return HttpResponse('success')
else:
form=DocumentForm(user=request.user)
context = { 'form':form, }
return render_to_response('sometemplate.html', context,
context_instance=RequestContext(request))
на самом деле вы, вероятно, захотите использовать get_or_create при создании вашего объекта Code вместо этого.
doc_code = Code(user_defined_code=user_defined_code, code=uniquecode)
Комментарии:
1. Спасибо за помощь. Я прочитал документы для ModelChoiceField, и теперь это имеет смысл. Вы знаете, как бы я отобразил CharField (третий пункт в моем вопросе) для
unique_code
поля? Я немного сократил свои модели, чтобы их было легче читать, но в основном у меня есть документ, которому присвоен сгенерированный компьютером уникальный код документа. Каждый пользователь может создать отдельный пользовательский код, который прикрепляется в качестве префикса к коду документа для всех документов, которыми он владеет, отсюда и причина для нескольких моделей.2. Есть некоторые другие вещи, которые нужно знать, например, предварительно заполнить виджет значением (это в представлении через
get_initial()
)3. Присвоение
self.fields['user_defined_code']
in__init__
некрасиво, но обычно этого не избежать: было бы приятнее объявитьuser_defined_code = ModelChoiceField(...)
как атрибут класса, но это редко возможно, потому чтоqueryset
аргумент обычно требует чего-то, что недоступно во время объявления класса формы.