1

ユーザーがプロジェクトを作成できるアプリを作成しています。各プロジェクト内で、写真を関連付けることができる「場所」を作成できます。写真は、他の多くのタイプのモデルに関連付けることができる一般的なコンテンツモデルです。この場合、写真はすでにアップロードされており、プロジェクトに関連付けられています。ユーザーは、javascriptモーダルウィンドウを介して場所に関連付けるものを選択し、「メモ」を追加できます。

もともと私はこれを完全に手動で作成し、request.POSTを介してビューの写真にアクセスしました。ただし、メモのテキスト値に問題があったため、適切に実行して実際のモデルフォームセットを作成する方が簡単/優れていると判断しました。

フォームの.instance属性にアクセスすると、写真がテンプレートに表示されます。

これは正常に機能しています。写真やメモを追加したり、以前に追加したことがある場合は場所から削除したりできます。ただし、問題は、フォームに検証エラーがあり、ユーザーがそれらを処理するためにテンプレートに戻った場合、画像自体が表示されないことです。これは、フォームにインスタンス属性がアタッチされていないことが原因のようです。写真は、その場所にすでに保存されている写真のタグ(簡単なサムネイルを使用)を介して問題なく表示されます<img src="{{MEDIA_URL}}{{ photo.instance.photo.small.url }}">が、追加/編集されたばかりの写真には表示されません。

私の質問は-この状況でどうすれば素敵なきれいな写真を表示できますか?

これが私のモデルフォームです:

class PhotoDisplayForm(ModelForm):

class Meta:
    model = Photo
    fields = {'id', 'note', }
    widgets = {
        'note': Textarea(attrs={'rows': 3}),
        'photo': HiddenInput(),
        'id': HiddenInput(),
    }

views.py

def location_form(request, project_id, location_id=None):
project = Project.objects.get(id=project_id)
photos_formset = []

if location_id is None:  #creates unbound forms
    locPhotoFS = formset_factory(PhotoDisplayForm, max_num=0, can_delete=True)
    photos_formset = locPhotoFS(prefix='loc_photos')

    use_type = 'create' #this variable is passed to the template to display appropriate text
    location_form = QuadratForm(request.POST or None, project_id=project_id)

else:   ### edit an existing form  ####
    use_type = 'edit'
    location = get_object_or_404(Location, pk=location_id)
    location_form = QuadratForm(request.POST or None, project_id=project_id)

    location_photos = Photo.objects.filter(location = location)
    locPhotoFS = modelformset_factory(Photo, PhotoDisplayForm, max_num=0,  can_delete=True)
    photos_formset = locPhotoFS(queryset = location_photos, prefix='loc_photos')            

if request.method == 'POST': 
    photos_formset = locPhotoFS(request.POST, prefix='loc_photos')

    if location_form.is_valid() and photos_formset.is_valid():
        location_instance = location_form.save(commit=False)
        location_instance.project = get_object_or_404(Project, pk=project_id)
        location_instance.save()

        for form in photos_formset:
            p = form.cleaned_data['id']
            if form.cleaned_data['DELETE']:
                p.content_object = project #reassociate the photo with the project
                p.save()
            else:   
                p.content_object = location_instance
                p.note = form.cleaned_data['note'].strip()
                print p.note
                p.save()

        return HttpResponseRedirect(reverse('core.views.location', args=(project_id, location_instance.id)))
    else:
        print 'there are errors'
context = {'location_type': location_type, 'use_type': use_type,'location_form': location_form,'project_photos': project.photos.all()}
if photos_formset:
    context['photos_formset'] = photos_formset
return render(request, 'location_form.html', context)

レンプレート

{% if photos_formset %}
    {% if location_form.non_field_errors %}{{ location_form.non_field_errors }}{% endif %}
    {{ photos_formset.management_form }} 
    {% for photo in photos_formset %}
    {% if photo.non_field_errors %}{{ photo.non_field_errors }}{% endif %}
    <div class="photo-details original" id="{{photo.instance.id}}_photo-details">
        <button type="button" photo="{{photo.instance.id}}" class="close pull-right photo-delete" aria-hidden="true">&times;</button>
        <div class="photo-notes">{{ photo.note.label_tag }}{{ photo.note|attr:"class:photo_notes_input" }}{{ photo.errors }}</div>
    {{ photo.id }}
    {{ photo.DELETE|attr:"class:delete-photo" }}
    <div class="thumbnail-caption">
    <img src="{{MEDIA_URL}}{{ photo.instance.photo.small.url }}">
    <br>{{ photo.instance.title }}
    </div>
    </div>
    {% endfor %}
    {% endif %}

役立つ場合は、写真モデル自体を次に示します。

class Photo(models.Model):

    title = models.CharField(max_length=30)
    photo = ThumbnailerImageField(upload_to=imagePath)
    object_id = models.PositiveIntegerField()
    content_type = models.ForeignKey(ContentType)
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    note = models.TextField(max_length=200, blank=True)

    def __unicode__(self):
        return self.title
4

1 に答える 1

0

私は(ややハッキーな)解決策を見つけました。テンプレートに渡されるproject_photosというクエリセットがすでにあるので(これにより、写真を選択して場所に追加できるjavascriptモーダルリストが作成されます)、テンプレート内でこれらをループして、IDが一致するものを見つけます(可変写真は、フォームセットループ内の現在のフォームです):

    <div class="thumbnail-caption">
        {% if photo.instance.title %}
        <img src="{{MEDIA_URL}}{{ photo.instance.photo.small.url }}">
        <br>{{ photo.instance.title }}
        {% else %}
            {% with p=photo.id.value %}
                {% for pp in project_photos %}
                    {% ifequal p|stringformat:"s" pp.id|stringformat:"s" %}
                        <img src="{{MEDIA_URL}}{{ pp.photo.small.url }}">
                        <br>{{ pp.title }}
                    {% endifequal %}
                {% endfor %}
            {% endwith %}
        {% endif %}
    </div>

stringformatテンプレートフィルターを使用する必要がありました-それは私をしばらく立ち往生させました。

これは完璧な解決策ではありません-それらの写真はまだ元のjavascriptウィンドウに表示されているため(明らかに私はそれを回避できます)-また、テンプレートはそれぞれのオブジェクトの潜在的に大きなリストをループする必要があり、速度が低下する可能性があります。

改善のための提案はありがたいことに受け入れられました。

于 2013-03-05T05:06:44.160 に答える