from django.core.management.base import BaseCommand
def Command(BaseCommand):
def handle(self, *args, **options):
self.stdout.write( "lol" )
So I tried creating a custom command in Django 1.8. It is in the directory appname/management/commands/commandname.py . However, trying to run the command using:
python manage.py commandname
yielded this error:
TypeError: Command() takes exactly 1 argument (0 given)
I've ensured that all the directories contain an __ init__.py file and that the app is added to the project. There doesn't seem to by much info on this online. Please do help.
Based on this doc page
(https://docs.djangoproject.com/en/1.8/howto/custom-management-commands/), you may want to change that line from def Command(BaseCommand): to class Command(BaseCommand):. (it looks like some further changes will be necessary as well)
Related
I'm new to Django, I have created a selenium project in which It automates mobile recharge. After completion of "recharge successful" I need it to send a successful receipt into my database. I used print(order_id.text) to get receipt in my terminal. now I don't know how to send that receipt to my database.
Probably the easiest way to implement this is with a custom management command [Django-doc]. In your amazon app, yoou can define a management command:
amazon/
management/
commands/
amazonpay.py
# …
In that amazonpay.py file, you then implement the custom management command:
# amazon/management/commands.amazonpay.py
from django.core.management.base import BaseCommand
from amazon.models import Amazon
class Command(BaseCommand):
help = 'Some description...'
def handle(self, *args, **options):
# … run selenium …
Amazon.objects.create(
o=ord_id
)
You can then run this command with:
python3 manage.py amazonpay
In fact runserver, makemigrations, etc. are all defined as management commands as well.
I have a python2.7 django project (I know, I am in 20th century!) that has some models in it. I need to override makemigrations so that the migration filenames are of the form 0001.py, 0002.py and so on, and not like 0001_initial.py, 0002_model1.py and so on which is by default what happens.
I already looked at how to create custom manage.py commands and I am able to override makemigrations command. Presently my code for the custom command (python2.7) looks like this:
path/to/project/app/management/commands/makemigrations.py
from django.core.management.commands.makemigrations import Command as CoreMakeMigrationsCommand
class Command(CoreMakeMigrationsCommand):
def handle(self, *args, **options):
super(Command, self).handle(*args, **options)
It is doing nothing more than calling the original makemigrations at the moment. I need to be able to modify the behaviour of how autodetector.py(which is part of the makemigrations flow) decides the naming of the files. In this file, there's method suggest_name as shown below:
#classmethod
def suggest_name(cls, ops):
"""
Given a set of operations, suggest a name for the migration they might
represent. Names are not guaranteed to be unique, but put some effort
into the fallback name to avoid VCS conflicts if possible.
"""
if len(ops) == 1:
if isinstance(ops[0], operations.CreateModel):
return ops[0].name_lower
elif isinstance(ops[0], operations.DeleteModel):
return "delete_%s" % ops[0].name_lower
elif isinstance(ops[0], operations.AddField):
return "%s_%s" % (ops[0].model_name_lower, ops[0].name_lower)
elif isinstance(ops[0], operations.RemoveField):
return "remove_%s_%s" % (ops[0].model_name_lower, ops[0].name_lower)
elif ops:
if all(isinstance(o, operations.CreateModel) for o in ops):
return "_".join(sorted(o.name_lower for o in ops))
return "auto_%s" % get_migration_name_timestamp()
The above gets called from here, in the same file in another method arrange_for_graph:
for i, migration in enumerate(migrations):
if i == 0 and app_leaf:
migration.dependencies.append(app_leaf)
if i == 0 and not app_leaf:
new_name = "0001_%s" % migration_name if migration_name else "0001_initial"
else:
new_name = "%04i_%s" % (
next_number,
migration_name or self.suggest_name(migration.operations)[:100],
)
I am new to overriding core files, and cannot figure out how to override only this part from my original custom command file, so that my requirements are met?
Also, please advise on how that is going to affect the subsequent calls to makemigrations, since they will be dependent on the new set of migrations files (with modified names).
Thanks
Ok, here is how I did it.
Create a makemigrations.py file (as shown in django docs for overriding manage.py commands), inside that create a Command class inheriting "django.core.management.commands.makemigrations.Command" and override the method write_migration_files, as show below:
from django.core.management.commands.makemigrations import Command as CoreMakeMigrationsCommand
class Command(CoreMakeMigrationsCommand):
def write_migration_files(self, changes):
for item in changes.values():
print('Overriding default names of migrations supplied by django core')
item[0].name = item[0].name.split('_')[0]
super(Command, self).write_migration_files(changes)
Unless you have hundreds of migrations, I think the easiest would be the following:
Create migrations one by one as you need but with the names decided by Django.
Rename the migrations:
Rename the files: 0002_migration_name.py -> 0002.py, etc.
Rename the references in the files, for example, replacing:
dependencies = [
('appname', '0002_migration_name'),
]
by:
dependencies = [
('appname', '0002'),
]
Only apply any migration when it, and all the previous ones, have the name you want.
I have a very simple case in which I want to run a script with python
myscript.py:
from models import Company
c = Company(number="1234567890", name="Company name")
models.py:
from django.db import models
class Company(models.Model):
number = models.CharField("company number", max_length=20, unique=True)
name = models.CharField("company name", max_length=30, unique=True)
class Meta:
verbose_name = "Company"
verbose_name_plural = "Companies"
I want to run python myscript.py or something like python manage.py execute_file myscript.py
I know my question is trivial and I can import a python manage.py shell environment, but that's not the point. Can I run it in a much simple manner?
Yes, Django has support for that: you define a custom command. It has some support for example to parse command parameters in a more convenient way.
You first need to define a file with the same name as the command you want (so here myscript.py). This should be placed in the app/management/commands/ directory (where app is an app of your system). So then the file tree looks like:
app/
__init__.py
management/
__init__.py
commands/
__init__.py
myscript.py
If you have not constructed any custom management commands before, you probably need to construct the files in boldface. The __init__.py files are simply empty files.
Then your command can look like:
# app/management/commands/myscript.py
from django.core.management.base import BaseCommand
from models import Company
class Command(BaseCommand):
def handle(self, *args, **options):
c = Company(number="1234567890", name="Company name")
Note that this script is actually not doing much: you construct a Company, but you do not store it in the database, so that means that usually the program will just stop, or raise an error in case the input is invalid.
You can then call your script with:
python3 manage.py myscript
and the command will also be listed in case you ask for help (with python3 manage.py help).
The Django tutorial on custom commands explains in more depth what you can do to parse commands, add helptext, etc.
I'm try to Execute Django shell command as cron,
I have some queries and objects tasks to search and read and write using the models and queries of my django app.
How can I execute this 1 or 2 times a day?
For example, how can I run these queries periodically:
from django.contrib.auth.models import User
from perfil.models import *
for user in usuarios:
profiles = Perfil.objects.filter(user=user)
create_task = Task.objects.create(user=user)
Take a look at Custom management commands for django.
As a basic example:
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User
from perfil.models import *
class Command(BaseCommand):
help = 'What does this do? '
def handle(self, *args, **options):
for user in usuarios:
profiles = Perfil.objects.filter(user=user)
create_task = Task.objects.create(user=user)
On a side note, you should be more explicit about your import and not use from perfil.models import *.
From that, you can execute the command based on the file you saved it in. If you saved the file in yourapp/management/commands/dofunstuff.py than you could execute it via python manage.py dofunstuff.
I've had some trouble trying to reset my cache every hour for a particular django view.
Right now, I am using the cache_page decorator to cache my view using Memcached. But the cache expires after a while and the request is uncached from some users.
#cache_page(3600)
def my_view(request):
...
How do I write my own django manage.py command to refresh my cache for this view every hour from cron?
In other words, what do I put in my refresh_cache.py file mentioned in the answer here:
Django caching - can it be done pre-emptively?
Thanks!
In your app, you can create a folder called management which contains another folder commands and an empty __init__.py file. Inside commands you create another __init__.py and a file where you write your custom command. Let's called it refresh.py:
# refresh.py
from django.core.management.base import BaseCommand, CommandError
from main.models import * # You may want to import your models in order to use
# them in your cron job.
class Command(BaseCommand):
help = 'Posts popular threads'
def handle(self, *args, **options):
# Code to refresh cache
Now you can add this file to your cron jobs. You can take a look at this tutorial but basically you use crontab -e to edit your cron jobs and crontab -l to see which cron jobs are running.
You can find all of this and more in the Django documentation.
I want to expand on Roberts answer to fill out the # Code to refresh cache
Timezome+location make caches much hard to work with, in my case I just disabled them, also I am not sure about using the test methods in the application code, but it seems to work nicely.
from django.core.management.base import BaseCommand, CommandError
from django.test.client import RequestFactory
from django.conf import settings
from ladder.models import Season
from ladder.views import season as season_view
class Command(BaseCommand):
help = 'Refreshes cached pages'
def handle(self, *args, **options):
"""
Script that calls all season pages to refresh the cache on them if it has expired.
Any time/date settings create postfixes on the caching key, for now the solution is to disable them.
"""
if settings.USE_I18N:
raise CommandError('USE_I18N in settings must be disabled.')
if settings.USE_L10N:
raise CommandError('USE_L10N in settings must be disabled.')
if settings.USE_TZ:
raise CommandError('USE_TZ in settings must be disabled.')
self.factory = RequestFactory()
seasons = Season.objects.all()
for season in seasons:
path = '/' + season.end_date.year.__str__() + '/round/' + season.season_round.__str__() + '/'
# use the request factory to generate the correct url for the cache hash
request = self.factory.get(path)
season_view(request, season.end_date.year, season.season_round)
self.stdout.write('Successfully refreshed: %s' % path)