autocomplete_light и django-dynamic-formset не работают вместе

Я пытаюсь использовать вместе autocomplete_light и django-dynamic-formset: оба работают по отдельности, но я не могу позволить им работать вместе... давайте начнем с кода...

модели.ру:

class Tmp_User(models.Model):
    userName   = models.CharField(max_length=200, blank=True, null=True,)
    firstName  = models.CharField(max_length=200, blank=True, null=True,)
    lastName   = models.CharField(max_length=200, blank=True, null=True,)
    ...
class Project(models.Model):
    title = models.CharField()
    ...
class Segment_in_Project(models.Model):
    name = models.CharField()
    the_project = models.ForeignKey('Project') 
    translator = models.ForeignKey('Tmp_User')
    ...

формы.py

autocomplete_light.autodiscover()

class AddProjectForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AddProjectForm, self).__init__(*args, **kwargs)
    class Meta:
        model = Project
        fields = '__all__'

class AddSegmentForm(autocomplete_light.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AddSegmentForm, self).__init__(*args, **kwargs)
    class Meta:
        model = Segment_in_Project
        autocomplete_exclude = ['the_project']
        fields = '__all__'

SegmentFormSet = formset_factory(AddSegmentForm)

autocomplete_light_registry.py

autocomplete_light.register(Tmp_User,
    search_fields=['^firstName', 'lastName'])

и views.py

class ProjectCreateView(CreateView):
    model = Project
    template_name = 'home/formset-table.html'
    form_class = AddProjectForm
    success_url = '/admin'

    def get(self, request, *args, **kwargs):
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        formset = SegmentFormSet()
        return self.render_to_response(
            self.get_context_data(
               form_Project=form,           
               formset_Segment=formset))

    def post(self, request, *args, **kwargs):
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        formset = SegmentFormSet(self.request.POST)
        if (form.is_valid() and formset.is_valid()):
            return self.form_valid(form, formset)
        else:
            return self.form_invalid(form, formset)

    def form_valid(self, form, formset):
        self.object = form.save()
        self.object.save()
        formset.instance = self.object
        formset.save()
        return super(ProjectCreateView, self).form_valid(form)

    def form_invalid(self, form, formset):
        return self.render_to_response(
            self.get_context_data(
                 form_Project=form, formset_Segment=formset))

Проблема в том, что экземпляр набора форм не "привязан" к модели проекта, и проверка не удалась: ошибка говорит, что the_project не определено... Сначала я попытался сохранить форму, получить идентификатор нового сохраненного проекта и передать его в набор форм вместе с запросом.POST, когда я устанавливаю набор форм... но это не сработало...

с другой стороны, использование inlineformset_factory(Project,Segment_in_Project) вместо formset_factory нарушает функциональность autocomplete_light... (я не знаю, как использовать autocomplete_light.ModelForm для набора форм Segment_in_Project)

Любая идея или предложения о том, как это сделать? Спасибо


person Attilio    schedule 28.01.2015    source источник


Ответы (1)


ХОРОШО. После МНОГО предварительных я нашел решение. Он не идеален в том смысле, что он делает то, что мне нужно, но у меня все еще есть ощущение, что должно быть что-то лучше...

Во всяком случае, то, что я сделал, это полностью взломать функцию публикации: сначала я сохраняю ProjectModel, затем я получаю идентификатор сохраненного проекта, затем я читаю информацию POST набора форм (в которой нет никакой информации об идентификаторе только что созданного проекта ), получаю необходимую информацию и создаю новый набор форм с правильным идентификатором проекта, а затем сохраняю его. Код ниже:

def post(self, request, *args, **kwargs):
    self.object = None
    form_class = self.get_form_class()
    form = self.get_form(form_class)
    form.instance.created_by = self.request.user
    formset = SegmentFormSet(self.request.POST)
    if form.is_valid():
        self.object = form.save()
    newdata = {}
    for idx, form in enumerate(formset):
        for field in form.fields:
            print idx, field, form[field].value()
            if field == 'the_project':
                tmp_field = u"form-%s-the_project"%(idx)
                newdata[tmp_field] = self.object.id
            elif field == 'id':
                pass
            else:
                tmp_field = u"form-%s-%s"%(idx,field)
                newdata[tmp_field] = form[field].value()
    newdata[u"form-MAX_NUM_FORMS"] = u"1000"
    newdata[u"form-MIN_NUM_FORMS"] = u"0"
    newdata[u"form-INITIAL_FORMS"] = u"0"
    newdata[u"form-TOTAL_FORMS"] = len(formset)
    newdata[u"title"] = self.object.title
    new_formset = SegmentFormSet(newdata)
    if new_formset.is_valid():
        return self.form_valid(form, new_formset)
    else:
        return self.form_invalid(form, new_formset)

Как видите, newdata DICT — это именно то, что мне нужно (включая идентификатор проекта) для корректного сохранения SegmentFormSet.

Если у кого-то есть лучшее решение... пожалуйста, дайте мне знать

person Attilio    schedule 01.02.2015