Посмотрите мой подробный ответ на очень похожий предыдущий вопрос
, @Beau Crawford является хорошим путем в SQL 2005 и ниже, хотя, если Вы предоставляете представителю, это должно перейти в первый парень к ТАК этому . Единственная проблема состоит в том, что для вставок это - все еще две операции IO.
мс Sql2008 представляет merge
из стандарта SQL:2003:
merge tablename with(HOLDLOCK) as target
using (values ('new value', 'different value'))
as source (field1, field2)
on target.idfield = 7
when matched then
update
set field1 = source.field1,
field2 = source.field2,
...
when not matched then
insert ( idfield, field1, field2, ... )
values ( 7, source.field1, source.field2, ... )
Теперь это - действительно всего одна операция IO, но ужасный код:-(
Сначала создайте форму модели автора.
author_form = AuthorModelForm()
затем создайте фиктивный объект автора:
author = Author()
Затем создайте встроенный набор форм, используя фиктивного автора следующим образом:
formset = BookFormSet(instance=author) #since author is empty, this formset will just be empty forms
Отправьте это на шаблон. После того, как данные возвращены обратно в представление, вы создаете автора:
author = AuthorModelForm(request.POST)
created_author = author.save() # in practice make sure it's valid first
Теперь подключите встроенный набор форм к вновь созданному автору и затем сохраните:
formset = BookFormSet(request.POST, instance=created_author)
formset.save() #again, make sure it's valid first
изменить:
Чтобы не было флажков в новых формах, выполните это шаблон:
{% for form in formset.forms %}
<table>
{% for field in form %}
<tr><th>{{field.label_tag}}</th><td>{{field}}{{field.errors}}</td></tr>
{% endfor %}
{% if form.pk %} {# empty forms do not have a pk #}
<tr><th>Delete?</th><td>{{field.DELETE}}</td></tr>
{% endif %}
</table>
{% endfor %}
models.py (Контакт)
class Contact(models.Model)
first = models.CharField(max_length=30)
middle = models.CharField('M.I.',max_length=30, blank=True)
last = models.CharField(max_length=30)
sort_order = models.PositiveIntegerField(default=99)
models.py (Ссылка)
class Link(models.Model):
contact = models.ForeignKey(Contact)
link = models.URLField()
description = models.CharField(max_length=30)
access_date = models.DateField(blank=True,null=True)
forms.py
from django.forms import ModelForm
from contacts.models import Contact
class ContactAjaxForm(ModelForm):
class Meta:
model=Contact
views.py
def edit(request,object_id=False):
LinkFormSet = inlineformset_factory(Contact, Link, extra=1)
if object_id:
contact=Contact.objects.get(pk=object_id)
else:
contact=Contact()
if request.method == 'POST':
f=forms.ContactAjaxForm(request.POST, request.FILES, instance=contact)
fs = LinkFormSet(request.POST,instance=contact)
if fs.is_valid() and f.is_valid():
f.save()
fs.save()
return HttpResponse('success')
else:
f = forms.ContactAjaxForm(instance=contact)
fs = LinkFormSet(instance=contact)
return render_to_response(
'contacts/edit.html',
{'fs': fs, 'f': f, 'contact': contact}
)
Это не основанный на примере в книге, он отредактирован из некоторого кода на моем сайте. Я не тестировал его, поэтому могут быть некоторые ошибки, но в целом он должен быть надежным. Использование пустого экземпляра Contact не является рекомендуемым методом, но он экономит немного логики и работает.
Изменить: