1

我正在构建一个用户可以创建项目的应用程序;在每个项目中,他们可以创建可以关联照片的“位置”。Photo 是一种通用的内容模型,可以与许多其他类型的模型相关联。在这种情况下,照片已经上传并与项目相关联。用户可以通过 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(),
    }

视图.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

I've figured out a (somewhat hacky) solution. Because I already have a queryset called project_photos which is being passed to the template (this creates the javascript modal list where photos can be selected to add to the location), I simply loop through these in the template and find one where the id matches (the variable photo is the current form within the formset loop):

    <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>

It was necessary to use the stringformat template filter - that got me stuck for a while.

This is not a perfect solution - because those photos are still displaying in the original javascript window (obviously I could work around that) - and also the template has to loop through a potentially large list of objects for each one which could slow things down.

Any suggestions for improvement gratefully accepted.

于 2013-03-05T05:06:44.160 回答