django/python: is one view that handles two sibling models a good idea?
Posted
by
clime
on Programmers
See other posts from Programmers
or by clime
Published on 2013-11-07T21:44:57Z
Indexed on
2013/11/09
16:13 UTC
Read the original article
Hit count: 237
I am using django multi-table inheritance: Video
and Image
are models derived from Media
. I have implemented two views: video_list
and image_list
, which are just proxies to media_list
. media_list
returns images or videos (based on input parameter model
) for a certain object, which can be of type Event
, Member
, or Crag
. The view alters its behaviour based on input parameter action
(better name would be mode
), which can be of value "edit" or "view".
The problem is that I need to ask whether the input parameter model
contains Video
or Image
in media_list
so that I can do the right thing. Similar condition is also in helper method media_edit_list
that is called from the view.
I don't particularly like it but the only alternative I can think of is to have separate (but almost the same) logic for video_list
and image_list
and then probably also separate helper methods for videos and images: video_edit_list
, image_edit_list
, video_view_list
, image_view_list
. So four functions instead of just two. That I like even less because the video functions would be very similar to the respective image functions. What do you recommend?
Here is extract of relevant parts: http://pastebin.com/07t4bdza. I'll also paste the code here:
#urls
url(r'^media/images/(?P<rel_model_tag>(event|member|crag))/(?P<rel_object_id>\d+)/(?P<action>(view|edit))/$', views.image_list, name='image-list')
url(r'^media/videos/(?P<rel_model_tag>(event|member|crag))/(?P<rel_object_id>\d+)/(?P<action>(view|edit))/$', views.video_list, name='video-list')
#views
def image_list(request, rel_model_tag, rel_object_id, mode):
return media_list(request, Image, rel_model_tag, rel_object_id, mode)
def video_list(request, rel_model_tag, rel_object_id, mode):
return media_list(request, Video, rel_model_tag, rel_object_id, mode)
def media_list(request, model, rel_model_tag, rel_object_id, mode):
rel_model = tag_to_model(rel_model_tag)
rel_object = get_object_or_404(rel_model, pk=rel_object_id)
if model == Image:
star_media = rel_object.star_image
else:
star_media = rel_object.star_video
filter_params = {}
if rel_model == Event:
filter_params['event'] = rel_object_id
elif rel_model == Member:
filter_params['members'] = rel_object_id
elif rel_model == Crag:
filter_params['crag'] = rel_object_id
media_list = model.objects.filter(~Q(id=star_media.id)).filter(**filter_params).order_by('date_added').all()
context = {
'media_list': media_list,
'star_media': star_media,
}
if mode == 'edit':
return media_edit_list(request, model, rel_model_tag, rel_object_id, context)
return media_view_list(request, model, rel_model_tag, rel_object_id, context)
def media_view_list(request, model, rel_model_tag, rel_object_id, context):
if request.is_ajax():
context['base_template'] = 'boxes/base-lite.html'
return render(request, 'media/list-items.html', context)
def media_edit_list(request, model, rel_model_tag, rel_object_id, context):
if model == Image:
get_media_edit_record = get_image_edit_record
else:
get_media_edit_record = get_video_edit_record
media_list = [get_media_edit_record(media, rel_model_tag, rel_object_id) for media in context['media_list']]
if context['star_media']:
star_media = get_media_edit_record(context['star_media'], rel_model_tag, rel_object_id)
else:
star_media = None
json = simplejson.dumps({
'star_media': star_media,
'media_list': media_list,
})
return HttpResponse(json, content_type=json_response_mimetype(request))
def get_image_edit_record(image, rel_model_tag, rel_object_id):
record = {
'url': image.image.url,
'name': image.title or image.filename,
'type': mimetypes.guess_type(image.image.path)[0] or 'image/png',
'thumbnailUrl': image.thumbnail_2.url,
'size': image.image.size,
'id': image.id,
'media_id': image.media_ptr.id,
'starUrl':reverse('image-star', kwargs={'image_id': image.id, 'rel_model_tag': rel_model_tag, 'rel_object_id': rel_object_id}),
}
return record
def get_video_edit_record(video, rel_model_tag, rel_object_id):
record = {
'url': video.embed_url,
'name': video.title or video.url,
'type': None,
'thumbnailUrl': video.thumbnail_2.url,
'size': None,
'id': video.id,
'media_id': video.media_ptr.id,
'starUrl': reverse('video-star', kwargs={'video_id': video.id, 'rel_model_tag': rel_model_tag, 'rel_object_id': rel_object_id}),
}
return record
# models
class Media(models.Model, WebModel):
title = models.CharField('title', max_length=128, default='', db_index=True, blank=True)
event = models.ForeignKey(Event, null=True, default=None, blank=True)
crag = models.ForeignKey(Crag, null=True, default=None, blank=True)
members = models.ManyToManyField(Member, blank=True)
added_by = models.ForeignKey(Member, related_name='added_images')
date_added = models.DateTimeField('date added', auto_now_add=True, null=True, default=None, editable=False)
class Image(Media):
image = ProcessedImageField(upload_to='uploads',
processors=[ResizeToFit(width=1024, height=1024, upscale=False)],
format='JPEG',
options={'quality': 75})
thumbnail_1 = ImageSpecField(source='image',
processors=[SmartResize(width=178, height=134)],
format='JPEG',
options={'quality': 75})
thumbnail_2 = ImageSpecField(source='image',
#processors=[SmartResize(width=256, height=192)],
processors=[ResizeToFit(height=164)],
format='JPEG',
options={'quality': 75})
class Video(Media):
url = models.URLField('url', max_length=256, default='')
embed_url = models.URLField('embed url', max_length=256, default='', blank=True)
author = models.CharField('author', max_length=64, default='', blank=True)
thumbnail = ProcessedImageField(upload_to='uploads',
processors=[ResizeToFit(width=1024, height=1024, upscale=False)],
format='JPEG',
options={'quality': 75}, null=True, default=None, blank=True)
thumbnail_1 = ImageSpecField(source='thumbnail',
processors=[SmartResize(width=178, height=134)],
format='JPEG',
options={'quality': 75})
thumbnail_2 = ImageSpecField(source='thumbnail',
#processors=[SmartResize(width=256, height=192)],
processors=[ResizeToFit(height=164)],
format='JPEG',
options={'quality': 75})
class Crag(models.Model, WebModel):
name = models.CharField('name', max_length=64, default='', db_index=True)
normalized_name = models.CharField('normalized name', max_length=64, default='', editable=False)
type = models.IntegerField('crag type', null=True, default=None, choices=crag_types)
description = models.TextField('description', default='', blank=True)
country = models.ForeignKey('country', null=True, default=None) #TODO: make this not null when db enables it
latitude = models.FloatField('latitude', null=True, default=None)
longitude = models.FloatField('longitude', null=True, default=None)
location_index = FixedCharField('location index', length=24, default='', editable=False, db_index=True) # handled by db, used for marker clustering
added_by = models.ForeignKey('member', null=True, default=None)
#route_count = models.IntegerField('route count', null=True, default=None, editable=False)
date_created = models.DateTimeField('date created', auto_now_add=True, null=True, default=None, editable=False)
last_modified = models.DateTimeField('last modified', auto_now=True, null=True, default=None, editable=False)
star_image = models.ForeignKey('Image', null=True, default=None, related_name='star_crags', on_delete=models.SET_NULL)
star_video = models.ForeignKey('Video', null=True, default=None, related_name='star_crags', on_delete=models.SET_NULL)
© Programmers or respective owner