Django: Run scripts from admin by selecting object's name - python

I am using Django 1.8 and Python 2.7.8 to create a web interface with MySQL databases, I can just use the Admin page to manipulate different tables. Suppose I have a student object with fields: name, id and gender. How to achieve some function like this:
select student's name: just avoid typo in names
click a button like "Run script"
trigger a Python program to run
I only need output from that Python program like: success or failure.
Thanks very much!

What you are after is admin actions. You write a custom function in the admin, and assign the function name to the admin_actions property.
def incomplete_tasks(modeladmin, request, queryset):
queryset.update(completed=False)
incomplete_tasks.short_description = 'Mark as Not Complete'
class TaskAdmin(admin.ModelAdmin):
list_display = ['title', 'completed']
ordering = ['created']
actions = [incomplete_tasks,]
admin.site.register(Task, TaskAdmin)
https://docs.djangoproject.com/en/1.8/ref/contrib/admin/actions/
https://godjango.com/78-custom-django-admin-actions/

Related

How to use different key name in MongoDB while working with Django?

I am working on developing a micro service using Django, where I use MongoDB as backend.
Folks who wrote the main code used java hence the data already present in the MongoDB collections follows camelcase pattern for e.g. firstName is the key name.
Now while working with python I like to name my variables and functions using snake casing like first_name and get_first_name().
What I want is that inside the code I want to refer first name as first_name everywhere but while saving/updating the first name in DB and while returning JSON response of the user data I want to return it as firstName?
Is there any way to achieve this behaviour? Please help me?
Use db_column as argument in your models field constructor as described here:
https://docs.djangoproject.com/en/4.0/ref/models/fields/#db-column
Edit: Regarding the API Output, you have two possibilities, either use a Serializer or the .values() function.
Serializer with django-restframework:
from rest_framework import serializers
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
serializer = CommentSerializer(comment)
serializer.data
# {'email': 'leila#example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}
https://www.django-rest-framework.org/api-guide/serializers/
.values(): Blog.objects.values('id', 'name') where the arguments define the output key values, https://docs.djangoproject.com/en/4.0/ref/models/querysets/#values

Django: How to switch relations between two objects

I am having issues updating a website I run. Essentially, the users on the website cannot be used anymore, so people have to create new accounts. However, users have ManyToMany relations with other tables in the database, and I want to be able to move the relations from the old users to the new ones.
Is there any good way to do this in Django or directly in the database? I am using PostgreSQL.
Django has a management command framework for this.
https://docs.djangoproject.com/en/3.1/howto/custom-management-commands/
This should live in PROJECT/APPNAME/management/commands/
from django.core.management import BaseCommand
from django.contrib.auth import get_user_model
User = get_user_model()
#The class must be named Command, and subclass BaseCommand
class Command(BaseCommand):
# Show this when the user types help
help = "fix users relations"
# A command must define handle()
def handle(self, *args, **options):
self.stdout.write("fixing users begin")
for user in User.objects.all():
...user fix code...
self.stdout.write("fix users complete")

How to attach a python file to each row(i.e. each data entry) in database formed using Django?

Ive used default django superuser to create an admin and created a DB using it. But now in that i want to add a python script to each data entry i.e. row. How do i do this???
Nothing special. Used basic Django.
There doesn't seem to be anything particularly complex here. You're just asking if you can use a field on the model to choose something; of course you can.
For instance:
# actions.py
def thing1(obj):
# do something with obj
def thing2(obj):
# do something else with obj
# models.py
from . import actions
ACTIONS = {
"do_thing_1": actions.thing1,
"do_thing_2": actions.thing2,
}
ACTION_CHOICES = [(action, action) for action in ACTIONS]
class MyModel(models.Model):
action = models.CharField(max_length=20, choices=ACTION_CHOICES)
def do_action(self):
return ACTIONS[self.action](self)

Updating Django Forms Dynamically

I have a simple form that provides a drop down menu of all available entries in a django Model.
forms.py
class SampleNameLookupForm(forms.Form):
#Make a list of sample name options for dropdown menu.
# Turn that into a list of tuples for ChoiceField.
samples = Sample.objects.all()
sample_list = [i.sample_name for i in samples]
sample_tuple = [(i, i) for i in sample_list]
Sample_Name = chosenforms.ChosenChoiceField(sample_tuple)
models.py
class Sample(models.Model):
sample_ID = models.CharField(max_length=20)
sample_name = models.CharField(max_length=30)
def __unicode__(self):
return self.sample_ID
class Meta:
ordering = ['id']
When I add a new sample to the model, I can see the new addition when accessing the model in mysql, or in the python manage.py shell, but it does not appear in the chosen field drop down menu.
When I restart the server, the form then reflects the new sample in the drop down menu. How can I update the drop down menu without restarting the server?
I should mention I am just locally hosting and am currently not in production.
The code needs to be inside the form's __init__ method, rather than directly in the class body, since the method is evaluated on each form instantation, rather than only when the class is defined.
class SampleNameLookupForm(forms.Form):
def __init__(self):
#Make a list of sample name options for dropdown menu.
# Turn that into a list of tuples for ChoiceField.
samples = Sample.objects.all().values_list('sample_name', flat=True)
sample_tuple = [(i, i) for i in samples]
self.fields['Sample_Name'] = chosenforms.ChosenChoiceField(sample_tuple)
Also note, I don't know what ChosenChoiceField is, but the standard Django forms library has a ModelChoiceField which is intended specifically for this use; it takes a queryset argument which is lazily evaluated, and therefore avoids the need for the __init__ stuff.

Is there a way to automatically add manager methods or class level methods to admin page in Django?

Let's say I have a class Person, which has bunch of manager methods and class level methods. I have the Person enabled in the admin page, but I am trying to find a way so that all these manager/class level methods automatically show on the admin page too.
class PersonManager(models.Manager):
def get_status(self, *args, **kwargs):
# code to get the status of selected persons
class Person(models.Model):
objects = PersonManager()
name = models.CharField(max_length=100)
def email_person(self, email):
#code to email the specific person
So for example, the email_person method would show up when I goto the detailed view on the admin page after selecting an instance. Or one of the manager methods can be invoked in the page of the admin that lists all the instances and I can select which instances I want the manager method to run on. Is there any way like that? I found an article that manually shows how to do so, but I was wondering if there is an existing solution/app that does that by default? http://patrick.arminio.info/additional-admin-views/
You can add admin actions to the list view by specifying them in your ModelAdmin:
class PersonAdmin(admin.ModelAdmin):
actions = ['some_action']
def some_action(self, queryset, request):
queryset.some_action()
some_action.short_description = "Do some action on selected persons"
Adding it to the detail view requires more work, but I've found that this method is generally sufficient.

Categories