3

I have created an app in a django project. This app has four models. I can add/modify/delete from admin site for all four models. But for one of the four models (say - ModelXYZ), I need to add a custom button for each entry in this table. Currently, I can see "Save", "Delete", etc. buttons for each entry present in ModelXYZ table. I need to add another button "Run", clicking on it will execute a python script written in that app only. Currently, I am running that script like this -

python manage.py shell
>>> execfile("my_app/my_script_1.py")
>>> execfile("my_app/my_script_2.py")

The script name is also stored in ModelXYZ table for each entry.

Django docs say that the admin site is customizable, but I am not very sure how can I run a python script by clicking on a button.

Pankaj Goyal
  • 1,448
  • 3
  • 15
  • 25
  • Why would you need a separate "Python script"? Why would you use "execfile" to run it? Why not put your code into a view and call it from a link, like any other Django code? – Daniel Roseman Apr 24 '16 at 13:08
  • This app is not meant to be used by any normal user. Some calculations are being done in this script and inserted into db. This script is to be run whenever db needs to be updated. That's why I want to add a button in admin site. – Pankaj Goyal Apr 24 '16 at 17:27
  • That doesn't answer my question *in any way at all*. Whether or not it is run by a normal or admin user, if you want to run code in response to a click then it should be in a view with a URL. – Daniel Roseman Apr 24 '16 at 17:35
  • I am pretty new to Django. If the whole operation takes time in order of hour, then is it feasible to do it using view? If yes, then how should I proceed? – Pankaj Goyal Apr 24 '16 at 18:07

2 Answers2

0

You can write a custom command: https://docs.djangoproject.com/en/1.9/howto/custom-management-commands/

Then from your code call the command with call_command: https://docs.djangoproject.com/en/1.9/ref/django-admin/#django.core.management.call_command

To call from the admin, you can create a custom action: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/actions/

Camilo Torres
  • 478
  • 2
  • 8
  • What would the benefit be of a command here? Especially if you're going to call it from Django code anyway. A command is useful if you're calling it from the command line or cron. – Daniel Roseman Apr 24 '16 at 16:01
  • Torres is right, but to the call_command, just extend the admin action to call your script. – Ohad the Lad Apr 25 '16 at 07:23
0

I solved it like this and it solves my purpose :-

class Site(models.Model):
    name = models.CharField(null=False, blank=False, max_length=256, unique=True)
    script = models.CharField(null=False, blank=False, max_length=256)
    def __unicode__(self):
       return u"{0}".format(self.name)

Then in my_app/admin.py, I wrote:-

from django.contrib import admin

from .models import *

def run(self, request, queryset):
    id=request.POST.get('_selected_action')
    siteObj=self.model.objects.get(pk=id)
    self.message_user(request, "Running: " + siteObj.script)
    execfile(siteObj.script)
run.short_description = "Run the script"

class SiteAdmin(admin.ModelAdmin):
    actions = [run]
    model = Site

# Register your models here.
admin.site.register(Site, SiteAdmin)
Pankaj Goyal
  • 1,448
  • 3
  • 15
  • 25
  • Is there any alternative to execfile() because it is blocking call? I want to execute the script in background, so that GUI does not block. – Pankaj Goyal Apr 29 '16 at 07:54
  • May be you are interested in these options: http://stackoverflow.com/questions/636561/how-can-i-run-an-external-command-asynchronously-from-python – Camilo Torres Apr 30 '16 at 16:28