0

m2mフィールドのクエリセットとウィジェットを変更するために、カスタムフォームオプションでinlineformset_factoryを使用しますezMapselected_mapCheckBoxSelectMultiple ウィジェットを使用して、現在の m2m フィールドを追加または削除するオプションをユーザーに提供するフォームが必要です。ただし、既に存在する他のオブジェクトを削除する機能をユーザーに提供したくありません。問題は、フォームセットを で保存するとformset.save_m2m()、フィールドが上書きされ、既に保存されているすべてのオブジェクトが消去されることです。

他のオブジェクトを消去せずに新しいオブジェクトを追加するにはどうすればよいですか?

ここに画像の説明を入力


モデル: (不要なフィールドの一部が削除されました)

class Shapefile(models.Model):
    filename = models.CharField(max_length=255)

class EzMap(models.Model):
    map_name = models.SlugField(max_length=50)
    layers = models.ManyToManyField(Shapefile, verbose_name='Layers to display', null=True, blank=True)

class LayerStyle(models.Model):
    styleName = models.SlugField(max_length=50)
    layer = models.ForeignKey(Shapefile)
    ezMap = models.ManyToManyField(EzMap)

フォーム:

class polygonLayerStyleFormset(forms.ModelForm):
    add_to_map = forms.BooleanField(required=False)
    def __init__(self, *args, **kwargs):
        self.map_selected =  kwargs.pop("map_selected", None)
        super(polygonLayerStyleFormset, self).__init__(*args, **kwargs)
        self.fields['conditionStyle'].help_text = "Put * if you want to select the entire table"
        self.fields['ezMap'].widget = forms.CheckboxSelectMultiple()
        self.fields['ezMap'].queryset = EzMap.objects.filter(id=self.map_selected.id)
        self.fields['ezMap'].help_text =""

    class Meta:
        model = LayerStyle

    def save(self, *args, **kwargs):
        instance = super(polygonLayerStyleFormset, self).save(*args, **kwargs)
        instance.add_to_map = self.cleaned_data['add_to_map']
        return instance


ftlStylePolygonFormset = inlineformset_factory(Shapefile, LayerStyle, can_delete=True, extra=1, max_num=5,
                fields = ['styleName', 'conditionStyle', 'fillColor', 'fillOpacity', 'strokeColor', 'strokeWeight', 'ezMap'], form=polygonLayerStyleFormset)

ビュー:

def setLayerStyle(request, map_name, layer_id):
    map_selected = EzMap.objects.get(map_name=map_name, created_by=request.user)
    layer_selected = Shapefile.objects.get(id=layer_id)
    layerStyle_selected = LayerStyle.objects.filter(layer=layer_selected)
    styleFormset = ftlStylePolygonFormset
    if request.POST:
        formset = styleFormset(request.POST, instance=layer_selected)
        if formset.is_valid():
            instances = formset.save()
            for instance in instances:
                if instance.add_to_map:
                    instance.ezMap.add(map_selecte)
                else:
                    instance.ezMap.remove(map_selected)
            save_link = u"/ezmapping/map/%s" % (map_name)
            return HttpResponseRedirect(save_link)
    else:
        formset = styleFormset(instance=layer_selected)
        #set initial data for add_to_map
        for form in formset:
            if form.instance.pk:
                if map_selected in form.instance.ezMap.all():
                    form.fields['add_to_map'].initial = {'add_to_map': True}
4

1 に答える 1

1

ezMapフォームフィールドで何をしているのか混乱しています。そのクエリセットを単一要素リストに設定してから、CheckboxSelectMultiple ウィジェットを使用します。ユーザーが一致するマップの選択を解除できるように設定していますが、新しいマップを追加することはできませんか?

初期化時にこれを行うには、カスタム基本フォームセット クラスを定義し、それをformset引数としてファクトリに渡す必要があります。

from django.forms.models import BaseInlineFormSet

class polygonLayerStyleForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.map_selected =  kwargs.pop("map_selected", None)
        super(polygonLayerStyleForm, self).__init__(*args, **kwargs)
        self.fields['conditionStyle'].help_text = "Put * if you want to select the entire table"
        self.fields['ezMap'].widget = forms.CheckboxSelectMultiple()
        self.fields['ezMap'].queryset = EzMap.objects.filter(id=self.map_selected.id)
        self.fields['ezMap'].help_text =""

    class Meta:
        model = LayerStyle

class polygonLayerStyleFormset(BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        self.map_selected =  kwargs.pop("map_selected", None)
        super(polygonLayerStyleFormset, self).__init__(*args, **kwargs)

    def _construct_form(self, i, **kwargs):
        kwargs['map_selected'] = self.map_selected
        return super(polygonLayerStyleFormset, self)._construct_form(i, **kwargs)

ftlStylePolygonFormset = inlineformset_factory(Shapefile, LayerStyle, formset=polygonLayerStyleFormset, form=polygonLaterStyleForm, # and other arguments as above
                                               )

ビューでフィールドを作成した後、フォームセットフォームを調べて、フィールドのクエリセットを直接変更する方が簡単な場合があります。

    formset = ftlStylePolygonFormset(instance=layer_selected)
    for form in formset.forms:
        form.fields['ezMap'].queryset = EzMap.objects.filter(id=map_selected.id)

そういえば、通常の規則では、ビューで POST と GET のケースを分割します。

from django.shortcuts import render

def setLayerStyle(request, map_name, layer_id):
    map_selected = EzMap.objects.get(map_name=map_name, created_by=request.user)
    layer_selected = Shapefile.objects.get(id=layer_id)
    layerStyle_selected = LayerStyle.objects.filter(layer=layer_selected)
    if request.method == 'POST':
        formset = ftlStylePolygonFormset(request.POST, instance=layer_selected, map_selected=map_selected)
        if formset.is_valid():
            instances = formset.save()
            save_link = u"/ezmapping/map/%s" % (map_name)
            return HttpResponseRedirect(save_link)
    else:
        formset = ftlStylePolygonFormset(instance=layer_selected, map_selected=map_selected)
    return render(request, "ezmapping/manage_layerStyle.html", {'layer_style': layerStyle_selected, 'layerStyleformset': formset, 'layer': layer_selected})

redirectまた、ターゲット URL をハードコーディングするよりも、ショートカットを使用して、成功したリダイレクトのビューを逆ルックアップすることをお勧めします。また、URL 引数に基づいてオブジェクトにアクセスするときに、または同等のものを使用するget_object_or_404と、現時点では偽の URL によって例外がトリガーされ、ユーザーに 500 ステータス エラーが発生しますが、これは望ましくありません。

ezMapリレーションシップに条件付きで追加するには:

class polygonLayerStyleForm(forms.ModelForm):
    add_to_map = forms.BooleanField()

    def save(self, *args, **kwargs):
        instance = super(polygonLayerStyleForm, self).save(*args, **kwargs)
        instance.add_to_map = self.cleaned_data['add_to-map']
        return instance

次に、ビューで:

instances = formset.save()
for instance in instances:
    if instance.add_to_map:
        instance.ezMap.add(map_selected)

save メソッドで呼び出しを行うこともできますが、その場合は、以前にマップをメンバー データとして設定する必要があり、さらに重要なことに、ケースaddに対処する必要があります。commit=False

于 2013-08-09T21:09:46.680 に答える