New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding list_fields command #1262
Conversation
Particularly helpful when you need to use related fields, but don't remember how to refer to the relation in your queries.
Well, I'm trying to be helpful, but I'm not passing checks. I initially thought it was because I left a blank line at the end. But now it's failing even more checks after deleting it. Anyone familiar with Travis CI have recommendations? |
Your are missing a newline at the end of the file. (see W391) |
@trbs my original commit had a newline, but failed one check. I'll try again. |
It says failing for flake8, but when I run flake8 locally I see no problems. |
Depends on the version of flake8 :-) |
Seems there is still a bit of trailing whitespace in |
Great ! One last question, could you please add some unittests for this command ? Thanks ! |
I'll work on adding this within the next couple days :) |
Great ! Please also use |
Could you merge this function first? Then I will apply the test case and |
@yeojin-dev think we can wait another month :-) |
@yeojin-dev & @trbs, I have a slightly improved version of this command I have been using in my projects. I'll update in the next day or two, and would love to work with @yeojin-dev on improvements/tests to get this ready for merging. |
@yeojin-dev & @trbs, I updated with the promised improvements. I'm glad someone else thinks this will be useful. My project is nearing 125 models, and it can be challenging to remember which models have what fields/methods. I use this script at least weekly, so hopefully it will benefit others. I'll get started on tests in a bit. Any help from @yeojin-dev will be much appreciated! |
Slightly updated version with some of my thoughts in them, take from it what you will :-) Some things I changed:
Food for thought:
Tests: As for tests I won't expect anything crazy here... let us just have some simple tests based on the output that can be generated from the (Note: I don't think we have many methods defined on models in our tests so we might need to add a couple) My suggestion for # -*- coding: utf-8 -*-
# Author: OmenApps. http://www.omenapps.com
import inspect
from django.apps import apps as django_apps
from django.core.management.base import BaseCommand
from django.db import connection
from django_extensions.management.utils import signalcommand
TAB = " "
HALFTAB = " "
class Command(BaseCommand):
"""A simple management command which lists model fields and methods."""
help = "List out the fields and methods for each model"
def add_arguments(self, parser):
super(Command, self).add_arguments(parser)
parser.add_argument(
'--field-class',
action='store_true', default=False,
help='show class name of field.'
)
parser.add_argument(
'--db-type',
action='store_true', default=False,
help='show database column type of field.'
)
parser.add_argument(
'--signature',
action='store_true', default=False,
help='show database column type of field.'
)
def list_model_info(self, options):
model_list = sorted(
django_apps.get_models(), key=lambda x: (x._meta.app_label, x._meta.object_name), reverse=False
)
for model in model_list:
self.stdout.write(model._meta.app_label + "." + model._meta.object_name)
self.stdout.write(HALFTAB + "Fields:")
for field in model._meta.get_fields():
if options['field_class']:
self.stdout.write(TAB + field.name + " - " + field.__class__.__name__)
elif options['db_type']:
self.stdout.write(TAB + field.name + " - " + field.db_type(connection=connection))
else:
self.stdout.write(TAB + field.name)
self.stdout.write(HALFTAB + "Methods (non-private/internal):")
for method_name in dir(model):
try:
method = getattr(model, method_name)
if callable(method) and not method_name.startswith("_") and not method_name[0].isupper():
if options['signature']:
signature = inspect.signature(method)
else:
signature = "()"
self.stdout.write(TAB + method_name + str(signature))
except AttributeError:
pass
self.stdout.write("\n")
self.stdout.write("Total Models in Project: %d" % len(model_list))
@signalcommand
def handle(self, *args, **options):
self.list_model_info(options) |
Awesome @trbs, I love these ideas and the help. I'll get working on some of this over the next week. |
@trbs: Alright, I made a bunch of changes:
|
@trbs, I added tests, but the TravisCI config includes three different databases, so the --db-field option fails on some tests no matter how I write the assertions due to the different representations in different databases. Any recommendations on an approach? It seems like tests for all variants could get complex really quickly. |
Modified command name and added listing of each model's methods Corrected order for entry of command in the docs Removed extra spaces on line endings.
Corrected flake 8 issues and formatted with black. Fixed line endings. Made it possible to use both db-type and field-class together Added tests Fixed trailing whitespace Corrected for representation in TravisCI
Very awesome ! |
As for tests.. I would think it would be okay to test on SQLite only... |
When working on projects with complex relations it can get confusing to remember how to refer to these relationships in queries. Additionally, sometimes it's annoying to dig through the models.py to find the field name of a particular field. The 'list_fields' command lists out all fields for each model within each installed app.