Updated container and freezer labels to be larger by request of Lorian.
[htsworkflow.git] / samplebc / samples / views.py
1 from django.http import HttpResponse, HttpResponseRedirect
2 from samplebc.samples import models
3 from django.core.exceptions import ObjectDoesNotExist
4 from django.template import Context, Template, RequestContext
5 from django.template.loader import get_template
6 from django.shortcuts import render_to_response
7 from django.contrib.auth.decorators import login_required
8
9 from django.utils.safestring import mark_safe
10
11 from samplebc.samples.forms import FreezerForm, ContainerForm, SampleForm, CmdMoveSampleForm
12 from samplebc.samples.models import Freezer, Container, Sample
13 from samplebc.samples.util import get_uuid, get_sampleid, assign_to_container
14 from samplebc.samples.errors import NoSpaceAvaliable
15 from samplebc import settings
16
17 # Barcode Magic!
18 from samplebc.bcmagic.forms import BarcodeMagicForm
19
20 # Reversion
21 from reversion import revision
22
23 import random
24 import ftplib
25 import StringIO
26
27
28 ################################################
29 # Util functions
30 ################################################
31
32 def print_zpl(zpl_text):
33     """
34     Sends zpl_text to printer
35     """
36     ftp = ftplib.FTP(host='131.215.54.194', user='blank', passwd='')
37     ftp.login()
38     ftp.storlines("STOR printme.txt", StringIO.StringIO(zpl_text))
39
40
41 def __center_line(line, width):
42     spaces_to_add = width - len(line)
43     
44     front_half = spaces_to_add / 2
45     back_half = spaces_to_add - front_half
46     
47     return (' ' * front_half) + line + (' ' * back_half)    
48
49
50   
51   
52 ################################################
53 # Container
54 ################################################
55 @login_required
56 def container_index(request):
57     """
58     Returns an index of available to containers
59     """
60     container_list = Container.objects.all()
61     c = Context({'title': 'Container Index',
62                  'container_list': container_list})
63     t = get_template('container_index.html')
64     
65     return render_to_response('app.html', {
66                                 'app_name': "HTSW-SampleTracker",
67                                 'page_name': 'Container Index',
68                                 'bcmagic': BarcodeMagicForm(),
69                                 'select': 'container',
70                                 'body': t.render(c)
71                             },
72                               context_instance=RequestContext(request))
73     
74
75
76 @login_required
77 def container_summary(request, container_id):
78     """
79     Returns details of a container
80     """
81     # Retrieve container by UUID
82     try:
83         container = models.Container.objects.get(uuid=container_id)
84     except ObjectDoesNotExist, e:
85         msg = "Container (%s) does not exist." % (container_id)
86         return render_to_response('app.html', {
87                                     'app_name': settings.HTSW_ST_APPNAME,
88                                     'page_name': 'Container Summary',
89                                     'media': '',
90                                     'bcmagic': BarcodeMagicForm(),
91                                     'select': 'container',
92                                     'body': msg
93                                 },
94                                   context_instance=RequestContext(request))
95     
96     # Retrieve samples from container
97     sample_list = container.sample_set.all()
98     
99     # Prepare a Sample Index of Contained Samples
100     cs = Context({'title': 'Contained Samples',
101                  'sample_list': sample_list})
102     ts = get_template('sample_index.html')
103     
104     # Render prepared samples into container summary
105     cc = Context({'container': container,
106                  'rendered_samples': ts.render(cs) })
107     tc = get_template('container_summary.html')
108     
109     # Render container summary to app html
110     return render_to_response('app.html', {
111                                 'app_name': settings.HTSW_ST_APPNAME,
112                                 'page_name': 'Container Summary',
113                                 'media': '',
114                                 'bcmagic': BarcodeMagicForm(),
115                                 'select': 'container',
116                                 'body': tc.render(cc)
117                             },
118                               context_instance=RequestContext(request))
119
120 @login_required
121 @revision.create_on_success
122 def container_add(request):
123     """
124     Form for adding a container.
125     """
126     #Reversion stuff
127     #revision.user = me
128     revision.comment = "New container created by user."
129     
130     # If user submitted the Container form.
131     if request.method == 'POST':
132         # Fill in ContainerForm with POSTed data.
133         form = ContainerForm(request.POST)
134         
135         # If the form is valid, process it.
136         if form.is_valid():
137             # Create new Container object from form data
138             c_obj = form.save(commit=False)
139             # Added UUID
140             c_obj.uuid = get_uuid()
141             # Save to DB.
142             c_obj.save()
143             # Save the many to many link data.
144             form.save_m2m()
145             return container_summary(request, c_obj.uuid)
146     else:
147         # If users first visit, create empty form.
148         form = ContainerForm()
149         
150     # Load form template
151     c = Context({'form': form,
152                  'action_url': '/samples/container/add/'})
153     t = get_template('generic_form.html')
154
155     return render_to_response('app.html', {
156                                 'app_name': settings.HTSW_ST_APPNAME,
157                                 'page_name': 'Container Add',
158                                 'media': form.media,
159                                 'bcmagic': BarcodeMagicForm(),
160                                 'select': 'container',
161                                 'body': t.render(c)
162                             },
163                               context_instance=RequestContext(request))
164
165 @login_required
166 @revision.create_on_success
167 def container_edit(request, container_id):
168     """
169     Allow editing of a container
170     """
171     #Reversion stuff
172     revision.comment = "Manual container edit by user."
173     
174     try:
175         container = models.Container.objects.get(uuid=container_id)
176     except ObjectDoesNotExist, e:
177         msg = "Container (%s) cannot be edited as it does not exist." % (container_id)
178         return render_to_response('app.html', {
179                                     'app_name': settings.HTSW_ST_APPNAME,
180                                     'page_name': 'Container Edit',
181                                     'media': '',
182                                     'bcmagic': BarcodeMagicForm(),
183                                     'select': 'container',
184                                     'body': msg
185                                 },
186                                   context_instance=RequestContext(request))
187     
188     # If user submitted the container form.
189     if request.method == 'POST':
190         # Fill in ContainerForm with POSTed data.
191         form = ContainerForm(request.POST, instance=container)
192         
193         # If the form is valid, process it.
194         if form.is_valid():
195             # Save Container object from form data
196             c_obj = form.save(commit=True)
197             # Save many2many changes as well
198             #form.save_m2m() #Not needed when form.save(commit=True)
199             
200             return container_summary(request, c_obj.uuid)
201     else:
202         # If users first visit, create form from Container instance.
203         form = ContainerForm(instance=container)
204
205     # Load form template
206     c = Context({'form': form,
207                  'action_url': '%sedit/' % (container.get_absolute_url())})
208     t = get_template('generic_form.html')
209
210     return render_to_response('app.html', {
211                                 'app_name': settings.HTSW_ST_APPNAME,
212                                 'page_name': 'Container Edit',
213                                 'media': form.media,
214                                 'bcmagic': BarcodeMagicForm(),
215                                 'select': 'container',
216                                 'body': t.render(c)
217                             },
218                               context_instance=RequestContext(request))
219
220 @login_required
221 def container_print(request, container_id):
222     """
223     prints a container label
224     """
225     
226     try:
227         container = models.Container.objects.get(uuid=container_id)
228     except ObjectDoesNotExist:
229         return HttpResponse('Container (%s) does not exist!' % (container_id))
230     
231     params = {}
232     params['container_name'] = __center_line(container.name[0:17], 17)
233     params['line1'] = __center_line('%s' % (container.name[17:34]), 17)
234     params['line2'] = __center_line('%s' % (container.name[34:51]), 17)
235     params['line3'] = __center_line('%s' % (container.name[51:68]), 17)
236     params['line4'] = __center_line('%s' % (container.name[68:85]), 17)
237     params['barcode'] = 'cntr|%s' % (container.uuid)
238     params['symbol'] = ''
239     
240     c = RequestContext(request, params)
241     t = get_template('zpl_container_label.txt')
242     print_zpl(t.render(c))
243     
244     return HttpResponse('print command for container %s sent.' % (container.uuid))
245
246
247 ################################################
248 # Freezer
249 ################################################
250 @login_required
251 def freezer_index(request):
252     """
253     Returns an index of available freezers
254     """
255     freezer_list = Freezer.objects.all()
256     c = Context({'freezer_list': freezer_list})
257     t = get_template('freezer_index.html')
258     
259     return render_to_response('app.html', {
260                                 'app_name': "HTSW-SampleTracker",
261                                 'page_name': 'Freezer Index',
262                                 'media': '',
263                                 'bcmagic': BarcodeMagicForm(),
264                                 'select': 'freezer',
265                                 'body': t.render(c)
266                             },
267                               context_instance=RequestContext(request))
268     
269 @login_required    
270 def freezer_summary(request, freezer_id):
271     """
272     Returns summary of freezer_id
273     """
274     # Retrieve freezer by UUID
275     try:
276         freezer = models.Freezer.objects.get(uuid=freezer_id)
277     except ObjectDoesNotExist, e:
278         msg = "Freezer (%s) does not exist." % (freezer_id)
279         return render_to_response('app.html', {
280                                     'app_name': settings.HTSW_ST_APPNAME,
281                                     'page_name': 'Freezer Summary',
282                                     'media': '',
283                                     'bcmagic': BarcodeMagicForm(),
284                                     'select': 'freezer',
285                                     'body': msg
286                                     },
287                                   context_instance=RequestContext(request))
288     
289     # List of contained containers
290     container_list = freezer.container_set.all()
291     
292     
293     # Render prepared container index into freezer summary
294     cf = Context({'freezer': freezer })
295     tf = get_template('freezer_summary.html')
296     
297     # Render Freezer summary to app html
298     return render_to_response('app.html', {
299                                 'app_name': settings.HTSW_ST_APPNAME,
300                                 'page_name': 'Freezer Summary',
301                                 'media': '',
302                                 'bcmagic': BarcodeMagicForm(),
303                                 'select': 'freezer',
304                                 'body': tf.render(cf)
305                             },
306                               context_instance=RequestContext(request))
307
308 @login_required
309 @revision.create_on_success
310 def freezer_add(request):
311     """
312     Allows you to add a new freezer.
313     """
314     #Reversion stuff
315     revision.comment = "New freezer created by user."
316     
317     # If user submitted the freezer form.
318     if request.method == 'POST':
319         # Fill in FreezerForm with POSTed data.
320         form = FreezerForm(request.POST)
321         
322         # If the form is valid, process it.
323         if form.is_valid():
324             # Create new Freezer object from form data
325             f_obj = form.save(commit=False)
326             # Added UUID
327             f_obj.uuid = get_uuid()
328             # Save to DB.
329             f_obj.save()
330             return freezer_summary(request, f_obj.uuid)
331     else:
332         # If users first visit, create empty form.
333         form = FreezerForm()
334
335     # Load form template
336     c = Context({'form': form,
337                  'action_url': '/samples/freezer/add/'})
338     t = get_template('generic_form.html')
339
340     return render_to_response('app.html', {
341                                 'app_name': settings.HTSW_ST_APPNAME,
342                                 'page_name': 'Freezer Add',
343                                 'media': form.media,
344                                 'bcmagic': BarcodeMagicForm(),
345                                 'select': 'freezer',
346                                 'body': t.render(c)
347                             },
348                               context_instance=RequestContext(request))
349
350 @login_required
351 @revision.create_on_success
352 def freezer_edit(request, freezer_id):
353     """
354     Allow editing of a freezer
355     """
356     #Reversion stuff
357     revision.comment = "Manual freezer edit by user."
358     
359     try:
360         freezer = models.Freezer.objects.get(uuid=freezer_id)
361     except ObjectDoesNotExist, e:
362         msg = "Freezer (%s) cannot be edited as it does not exist." % (freezer_id)
363         return render_to_response('app.html', {
364                                     'app_name': settings.HTSW_ST_APPNAME,
365                                     'page_name': 'Freezer Summary',
366                                     'media': '',
367                                     'bcmagic': BarcodeMagicForm(),
368                                     'select': 'freezer',
369                                     'body': msg
370                                     },
371                                   context_instance=RequestContext(request))
372     
373     # If user submitted the freezer form.
374     if request.method == 'POST':
375         # Fill in FreezerForm with POSTed data.
376         form = FreezerForm(request.POST, instance=freezer)
377         
378         # If the form is valid, process it.
379         if form.is_valid():
380             # Save Freezer object from form data
381             f_obj = form.save(commit=True)
382             
383             return freezer_summary(request, f_obj.uuid)
384     else:
385         # If users first visit, create form from freezer instance.
386         form = FreezerForm(instance=freezer)
387
388     # Load form template
389     c = Context({'form': form,
390                  'action_url': '%sedit/' % (freezer.get_absolute_url())})
391     t = get_template('generic_form.html')
392
393     return render_to_response('app.html', {
394                                 'app_name': settings.HTSW_ST_APPNAME,
395                                 'page_name': 'Freezer Edit',
396                                 'media': form.media,
397                                 'bcmagic': BarcodeMagicForm(),
398                                 'select': 'freezer',
399                                 'body': t.render(c)
400                             },
401                               context_instance=RequestContext(request))
402
403 @login_required
404 def freezer_print(request, freezer_id):
405     """
406     prints a freezer label
407     """
408     
409     try:
410         freezer = models.Freezer.objects.get(uuid=freezer_id)
411     except ObjectDoesNotExist:
412         return HttpResponse('Freezer (%s) does not exist!' % (freezer_id))
413     
414     params = {}
415     params['freezer_name'] = __center_line(freezer.name, 17)
416     params['line1'] = __center_line('%s' % (freezer.name[17:34]), 17)
417     params['line2'] = __center_line('%s' % (freezer.name[34:51]), 17)
418     params['line3'] = __center_line('%s' % (freezer.name[51:68]), 17)
419     params['line4'] = __center_line('Temp: %s C' % (freezer.temperature), 17)
420     params['barcode'] = 'frzr|%s' % (freezer.uuid)
421     params['symbol'] = ''
422     
423     c = RequestContext(request, params)
424     t = get_template('zpl_freezer_label.txt')
425     print_zpl(t.render(c))
426     
427     return HttpResponse('print command for freezer %s sent.' % (freezer.uuid))
428
429
430 ################################################
431 # Samples
432 ################################################
433 @login_required
434 def sample_index(request):
435     """
436     return a list of samples and what we can do with them.
437     """
438     sample_list = models.Sample.objects.all()
439     
440     # Load form template
441     c = Context({'title': 'Sample Index',
442                  'sample_list': sample_list})
443     t = get_template('sample_index.html')
444     #html.append('%s <a href="/samples/sample/%s/print">(print)</a>' \
445     #            % (sample, sample.sampleid))
446         
447     return render_to_response('app.html', {
448                                 'app_name': settings.HTSW_ST_APPNAME,
449                                 'page_name': 'Samples Index',
450                                 'media': '',
451                                 'bcmagic': BarcodeMagicForm(),
452                                 'select': 'samples',
453                                 'body': t.render(c)
454                             },
455                               context_instance=RequestContext(request))
456
457 @login_required
458 def sample_homeless(request):
459     """
460     Returns an index of homeless samples
461     """
462     sample_list = Sample.objects.filter(container=None)
463     c = Context({'title': 'Homeless Samples',
464                  'sample_list': sample_list})
465     t = get_template('sample_homeless.html')
466     
467     return render_to_response('app.html', {
468                                 'app_name': "HTSW-SampleTracker",
469                                 'page_name': 'Homeless Samples',
470                                 'bcmagic': BarcodeMagicForm(),
471                                 'select': 'samples',
472                                 'body': t.render(c)
473                             },
474                               context_instance=RequestContext(request))
475     
476 @login_required
477 @revision.create_on_success
478 def sample_add(request):
479     """
480     Allow adding of a new sample
481     """
482     #Reversion stuff
483     revision.comment = "New sample created by user."
484     
485     ASSIGNED_CONTAINER = False
486     
487     # If user submitted the sample form.
488     if request.method == 'POST':
489         # Fill in SampleForm with POSTed data.
490         form = SampleForm(request.POST)
491         
492         # If the form is valid, process it.
493         if form.is_valid():
494             # Create new Sample object from form data
495             s_obj = form.save(commit=False)
496             
497             # Add sample ID
498             s_obj.sampleid = get_sampleid()
499             
500             # If the user wants us to assign a container.
501             if form.cleaned_data['assign_container']:
502                 # Choose container
503                 try:
504                     assign_to_container(s_obj)
505                     ASSIGNED_CONTAINER = True
506                 except NoSpaceAvaliable, e:
507                     #return HttpResponse("<b>Error:</b> %s<br /><i>You will need to prepare a new container before continuing.</i>" \
508                     #                    % (e))
509                     ASSIGNED_CONTAINER = False
510                                     
511             # Save to DB.
512             s_obj.save()
513             
514             if not ASSIGNED_CONTAINER:
515                 msg = "NOTE: Sample is homeless"
516                 return sample_summary(request, s_obj.sampleid, msg=msg)
517
518             
519             msg = "Sample created."
520             return sample_summary(request, s_obj.sampleid, msg=msg)
521     else:
522         # If users first visit, create empty form.
523         form = SampleForm()
524
525     # Load form template
526     c = Context({'form': form,
527                  'action_url': '/samples/sample/add/'})
528     t = get_template('generic_form.html')
529
530     return render_to_response('app.html', {
531                                 'app_name': settings.HTSW_ST_APPNAME,
532                                 'page_name': 'Sample Add',
533                                 'media': form.media,
534                                 'bcmagic': BarcodeMagicForm(),
535                                 'select': 'samples',
536                                 'body': t.render(c)
537                             },
538                               context_instance=RequestContext(request))
539     
540 @login_required
541 @revision.create_on_success
542 def sample_edit(request, sampleid):
543     """
544     Allow editing of a sample
545     """
546     #Reversion stuff
547     revision.comment = "Manual sample edit by user."
548     
549     try:
550         sample = models.Sample.objects.get(sampleid=sampleid)
551     except ObjectDoesNotExist, e:
552         msg = "Sample (%s) cannot be edited as it does not exist." % (sampleid)
553         return render_to_response('app.html', {
554                     'app_name': settings.HTSW_ST_APPNAME,
555                     'page_name': 'Sample Edit',
556                     'media': '',
557                     'bcmagic': BarcodeMagicForm(),
558                     'select': 'samples',
559                     'body': msg
560                 })
561     
562     # If user submitted the sample form.
563     if request.method == 'POST':
564         # Fill in SampleForm with POSTed data.
565         form = SampleForm(request.POST, instance=sample)
566         
567         # If the form is valid, process it.
568         if form.is_valid():
569             # Save Sample object from form data
570             s_obj = form.save(commit=True)
571             
572             msg = "Sample Update Saved"
573             return sample_summary(request, s_obj.sampleid, msg)
574     else:
575         # If users first visit, create form from sample instance.
576         form = SampleForm(instance=sample)
577
578     # Load form template
579     c = Context({'form': form,
580                  'action_url': '%sedit/' % (sample.get_absolute_url())})
581     t = get_template('generic_form.html')
582
583     return render_to_response('app.html', {
584                                 'app_name': settings.HTSW_ST_APPNAME,
585                                 'page_name': 'Sample Edit',
586                                 'media': form.media,
587                                 'bcmagic': BarcodeMagicForm(),
588                                 'select': 'samples',
589                                 'body': t.render(c)
590                             },
591                               context_instance=RequestContext(request))
592
593 @login_required
594 @revision.create_on_success
595 def sample_assign_container(request, sampleid):
596     """
597     Assigns sample to container using the assign to container algorithm
598     """
599     
600     sample = Sample.objects.get(sampleid=sampleid)
601     
602     try:
603         assign_to_container(sample)
604     except NoSpaceAvaliable, e:
605         return render_to_response('app.html', {
606                                     'app_name': settings.HTSW_ST_APPNAME,
607                                     'page_name': 'Sample Assign',
608                                     'media': '',
609                                     'bcmagic': BarcodeMagicForm(),
610                                     'select': 'samples',
611                                     'body': mark_safe("<b>Error:</b> %s<br /><i>You will need to prepare a new container before continuing.</i>" \
612                                                         % (e))
613                                     },
614                                   context_instance=RequestContext(request))
615         
616     sample.save()
617     
618     body = 'Sample (<a href="%s">%s</a>) assigned to container (<a href="%s">%s</a>)' \
619            % (sample.get_absolute_url(), str(sample), sample.container.get_absolute_url(), str(sample.container))
620     
621     #Reversion stuff
622     revision.comment = "Sample auto-assigned to container (%s: %s)" % (str(sample.container), sample.container.uuid)
623     
624     return render_to_response('app.html', {
625                                 'app_name': settings.HTSW_ST_APPNAME,
626                                 'page_name': 'Sample Assign',
627                                 'media': '',
628                                 'bcmagic': BarcodeMagicForm(),
629                                 'select': 'samples',
630                                 'body': mark_safe(body),
631                             },
632                             context_instance=RequestContext(request))
633
634 @login_required
635 def sample_summary(request, sampleid, msg=None):
636     """
637     Display a summary of a given sample
638     """
639     try:
640         sample = models.Sample.objects.get(sampleid=sampleid)
641     except ObjectDoesNotExist, e:
642         msg = "Sample (%s) does not exist." % (sampleid)
643         return render_to_response('app.html', {
644                                     'app_name': settings.HTSW_ST_APPNAME,
645                                     'page_name': 'Sample Summary',
646                                     'media': '',
647                                     'bcmagic': BarcodeMagicForm(),
648                                     'select': 'samples',
649                                     'body': msg
650                                 },
651                                   context_instance=RequestContext(request))
652     
653     c = Context({'sample': sample,
654                  'msg': msg,})
655     t = get_template('sample_summary.html')
656     
657     return render_to_response('app.html', {
658                                 'app_name': settings.HTSW_ST_APPNAME,
659                                 'page_name': 'Sample Summary',
660                                 'media': '',
661                                 'bcmagic': BarcodeMagicForm(),
662                                 'select': 'samples',
663                                 'body': t.render(c)
664                             },
665                               context_instance=RequestContext(request))
666
667 @login_required  
668 def sample_print(request, sampleid):
669     """
670     prints a sample!
671     """
672     
673     try:
674         sample = models.Sample.objects.get(sampleid=sampleid)
675     except ObjectDoesNotExist:
676         return HttpResponse('Sample (%s) does not exist!' % (sampleid))
677     
678     params = {}
679     params['fullid'] = str(sample)
680     params['sampleid'] = __center_line("s|%s" % (sample.sampleid), 16)
681     params['line1'] = __center_line(sample.name[0:10], 10)
682     params['line2'] = __center_line(sample.name[10:25], 14)
683     params['line3'] = __center_line('ExpType %s' % (sample.sample_type.name[0:8]), 15)
684     params['slot_num'] = random.randint(1,81)
685     
686     c = RequestContext(request, params)
687     t = get_template('half_inch_samples.txt')
688     print_zpl(t.render(c))
689     
690     return HttpResponse('print command for sample %s sent.' % (sample.sampleid))
691
692 @login_required
693 def user_profile(request):
694     """
695     Information about the user
696     """
697     return render_to_response('registration/profile.html', {
698                                 'app_name': settings.HTSW_ST_APPNAME,
699                                 'page_name': 'User Profile',
700                                 'media': '',
701                                 'bcmagic': BarcodeMagicForm(),
702                                 'select': 'settings',
703                             },
704                               context_instance=RequestContext(request))
705
706 ################################################
707 # Barcode Magic Commands
708 ################################################
709
710 def __cmd_move_sample_return(form, request, msg=''):
711     """
712     A small helper function since this code is reused multiple times
713     """
714     # Load form template
715     c = Context({'form': form,
716                  'action_url': '.'})
717     t = get_template('generic_form.html')
718     
719     return render_to_response('app.html', {
720                                 'app_name': settings.HTSW_ST_APPNAME,
721                                 'page_name': 'CMD: Move Sample',
722                                 'media': '',
723                                 'bcmagic': BarcodeMagicForm({'bcm_mode': 'cmd_move_sample'}),
724                                 'select': 'samples',
725                                 'msg': msg,
726                                 'body': t.render(c)
727                             },
728                               context_instance=RequestContext(request))
729
730 @login_required
731 @revision.create_on_success
732 def cmd_move_sample(request):
733     """
734     Moves a sample to a target container
735     """
736     form = CmdMoveSampleForm()
737     # Process form:
738     if request.method == 'POST':
739         form = CmdMoveSampleForm(request.POST)
740         
741         #If for some reason the form is not valid, return
742         if not form.is_valid():
743             msg = "Form is not valid."
744             return __cmd_move_sample_return(form, request, msg)
745         
746         try:
747             sample = models.Sample.objects.get(sampleid=form.cleaned_data['sampleid'])
748         except ObjectDoesNotExist, e:
749             msg = "Sample %s does not exist." % (form.cleaned_data['sampleid'])
750             return __cmd_move_sample_return(form, request, msg)
751             
752         try:
753             container = models.Container.objects.get(uuid=form.cleaned_data['container_id'])
754         except ObjectDoesNotExist, e:
755             msg = "Container %s does not exist." % (form.cleaned_data['container_id'])
756             return __cmd_move_sample_return(form, request, msg)
757         
758         # Move the sample to the new container
759         old_container = sample.container
760         sample.container = container
761         if old_container is None:
762             revision.comment = "Sample (%s) moved from Homeless to Container(%s; uuid: %s)" \
763                                % (str(sample), str(container), container.uuid)
764         else:
765             revision.comment = "Sample (%s) moved from Container(%s; uuid: %s) to Container(%s; uuid: %s)" \
766                                % (str(sample), str(old_container), old_container.uuid, str(container), container.uuid)
767         sample.save()
768         
769         return __cmd_move_sample_return(CmdMoveSampleForm(), request, revision.comment)
770         
771     return __cmd_move_sample_return(form, request)
772         
773         
774     
775