1

我想为用户提供基于现有出版物创建新出版物的可能性。为此,我希望他们单击​​指向“basedview”的链接,其中包含他们希望新项目基于的出版物的 id。包含两个用于 n:n 关系的表单集。

这应该打开一个预填充的表单,其中包含所有字段 prefield 以及它所基于的出版物中的数据。一旦用户根据需要进行了更改,它应该为字段集保存一个新的发布和新的关系——后者是其中的困难部分。

所以我的问题是 - 如何从数据库中加载所有相应的表单集,然后删除它们的所有 pk 但仍保持与发布项目的关系?

现在在get方法中是这样的:

        self.object = None
        try:
            self.object = KombiPublikation.objects.get(pk=self.kwargs['pk'])
        except ObjectDoesNotExist:
            raise Http404("Keinen Output unter dieser PubID gefunden.")

        form = KombiPublikationForm(instance=self.object)
        pubspr_formset = KombiPublikationSpracheFormset(instance=self.object)
        pubpers_formset = KombiPublikationPersonFormset(instance=self.object)

但这最终只是对现有出版物的编辑。在填充表单集或找到一种以不同方式填充表单集的方法后,我必须以某种方式删除 pk 。有任何想法吗?

非常感谢你!

这里是完整的代码摘录:

class PublikationBasedView(PublikationCreateView):
    def get(self, request, *args, **kwargs):
        self.object = None
        try:
            self.object = KombiPublikation.objects.get(pk=self.kwargs['pk'])
        except ObjectDoesNotExist:
            raise Http404("Keinen Output unter dieser PubID gefunden.")

        #todo: delete the pk of all objects in forms in formset, else they stay the same and are also changed!!
        #fix: delete pk in objekt in order to save it as a new objekt - else based does not work at all!

        #self.object.pk=None

        form = KombiPublikationForm(instance=self.object)
        pubspr_formset = KombiPublikationSpracheFormset(instance=self.object)
        pubpers_formset = KombiPublikationPersonFormset(instance=self.object)



        return self.render_to_response(
            self.get_context_data(
                form=form,
                pubspr_formset=pubspr_formset,
                pubpers_formset=pubpers_formset,
            )
        )

#its based on this create view
class PublikationCreateView(LoginRequiredMixin, ShowNumberOfItems, CreateView):
    form_class = KombiPublikationForm
    template_name = 'output/pub_create.html'
    model = KombiPublikation

    def get(self, request, *args, **kwargs):
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        pubspr_formset = KombiPublikationSpracheFormset()
        pubpers_formset = KombiPublikationPersonFormset()

        return self.render_to_response(
            self.get_context_data(
                form=form,
                pubspr_formset=pubspr_formset,
                pubpers_formset=pubpers_formset
            )
        )

    def post(self, request, *args, **kwargs):
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        pubspr_formset = KombiPublikationSpracheFormset(self.request.POST)
        pubpers_formset = KombiPublikationPersonFormset(self.request.POST)

        if form.is_valid() and pubspr_formset.is_valid() and pubpers_formset.is_valid():
            return self.form_valid(form, pubspr_formset, pubpers_formset)
        else:
            return self.form_invalid(form, pubspr_formset, pubpers_formset)

    def get_success_msg(self):
        return 'Ihr Output wurde erfolgreich unter PubID {} angelegt. Speicherort: {}. <br>'.format(self.object.pk, self.object.status)

    def form_valid(self, form, pubspr_formset, pubpers_formset):
        """ Called if all forms are valid."""
        self.object = form.save()
        pubspr_formset.instance = self.object
        pubspr_formset.save()
        pubpers_formset.instance = self.object
        pubpers_formset.save()

        messages.success(self.request, self.get_success_msg())
        return redirect(self.get_success_url())

    def form_invalid(self, form, pubspr_formset, pubpers_formset):
        """ Called if whether a form is invalid. Re-renders data-filled forms and errors."""


        return self.render_to_response(
                        self.get_context_data(
                                form=form,
                                pubspr_formset=pubspr_formset,
                                pubpers_formset=pubpers_formset,

                        ))
4

2 回答 2

1

一旦您设置了表单instance,它就会绑定到该对象。所有更新都将针对您传递的对象。

相反,您需要设置表单的initial

使用 initial 在运行时声明表单字段的初始值。例如,您可能想用当前会话的用户名填写用户名字段。

然后有一个实用程序django.forms.models.model_to_dict可以为您提供所需的字典initial

instance返回一个包含适合作为表单initial关键字参数传递的数据的字典。

所以你需要做这样的事情:

from django.forms.models import model_to_dict

object = # Your code here...

# You don't want `id`. Possibly others...?
initial_data = model_to_dict(object, exclude=['id'])

form = YourFormClass(initial=initial_data)

# ...

希望这会有所帮助。

于 2016-11-29T10:51:28.147 回答
0

我解决了这个问题,因为它比预期的要复杂一些,所以我在这里分享我的发现 - 如果有人找到更简单的解决方案,请随时添加另一条评论

这是视图中的最终 get 方法:

def get(self, request, *args, **kwargs):
    self.object = None
    try:
        self.object = KombiPublikation.objects.get(pk=self.kwargs['pk'])
    except ObjectDoesNotExist:
        raise Http404("Keinen Output unter dieser PubID gefunden.")

    #load all form initials and render the form correctly - but save new objects
    #1. make sure the main publikation object is saved as a new object:
    self.object.pk = None
    self.object.erstellungsdatum = datetime.now()
    form = KombiPublikationForm(instance=self.object)

    #2. get the corresponding querysets for sprache and person:
    pubspr = KombiPublikationSprache.objects.filter(publikation=self.kwargs['pk'])
    pubpers = KombiPublikationPerson.objects.filter(publikation=self.kwargs['pk'])

    #make a list of dicts out of the querysets and delete pk id and fk relations
    pubspr_listofdicts = []
    for pubspr in pubspr:
        pubspr_dict= model_to_dict(pubspr)
        del pubspr_dict['id']
        del pubspr_dict['publikation']
        pubspr_listofdicts.append(pubspr_dict)

    pubpers_listofdicts = []
    for pubpers in pubpers:
        pubpers_dict=model_to_dict(pubpers)
        del pubpers_dict['id']
        del pubpers_dict['publikation']
        pubpers_listofdicts.append(pubpers_dict)

    #create new formsets with the right amount of forms (leng(obj_listofdicts)
    KombiPublikationSpracheFormset = inlineformset_factory(KombiPublikation,
                                                           KombiPublikationSprache,
                                                           form=KombiPublikationSpracheForm,
                                                           extra=len(pubspr_listofdicts),
                                                           can_delete=True,
                                                           can_order=True,
                                                           min_num=1,
                                                           validate_min=True)

    KombiPublikationPersonFormset = inlineformset_factory(
        KombiPublikation,
        KombiPublikationPerson,
        form=KombiPublikationPersonForm,
        extra=len(pubpers_listofdicts),
        can_delete=True,
        can_order=True,
        min_num=0,
        validate_min=True)

    #initiate the formset with initial data:
    pubspr_formset = KombiPublikationSpracheFormset(instance=self.object, initial=pubspr_listofdicts)
    pubpers_formset = KombiPublikationPersonFormset(instance=self.object, initial=pubpers_listofdicts)


    return self.render_to_response(
        self.get_context_data(
            form=form,
            pubspr_formset=pubspr_formset,
            pubpers_formset=pubpers_formset,
        )
    )
于 2016-12-06T14:46:58.353 回答