How to "autodiscover" a different location for the admin.py file? - python

I think it makes sense to organize my Django apps in a different way (by protocol):
📂myapp
apps.py
models.py
utilities.py
📂html
admin.py
urls.py
views.py
📂rest
serializers.py
urls.py
views.py
📂graphql
etc
This would move the admin.py file into the html folder, but sadly autodiscover does not seem to find it anywhere else than in the myapp folder. Is there a way to point to the correct location: perhaps in apps.py? I am sure a symlink would work, but not really what I am after.

There's nothing magic about either admin.py or autodiscover. All admin.py does is run any register calls on import, and all autodiscover does is look for an admin.py file in each installed app and import it. There's nothing to stop you importing your admin.py in its custom location from somewhere else, eg the models or views files.

This was somewhat tricky, but the comment by #Joran Beasley set me in the right direction.
For admin.py to be autodiscovered it needs to be either in the top level app folder, or be imported in a file. However... not every file works.
If you do from .html import admin
into __init__.py or apps.py: django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
into models.py: Results in an importerror from models into admin. I think due to the circular nature of the imports.
However the following works: from . import admin inside the urls.py. Make sure to add a comment that this import is needed for autodiscover purposes.

Related

Django 2.1: How to import models in a custom .py file?

I'm currently working on a Django project that has the following structure
django_project/
django_app/
views.py
models.py
urls.py
src/
myCustomFile.py
In this context, I would like to import the models in myCustomFile.py.
Usually, to import models in other files I include the following line of code
from django_app.models import *
but apparently, I do not seem to work. I think that the problem could be due to the fact that myCustomFile.py is in a subfolder. For this reason, I also tried to move myCustomFile.py at the same level of models.py but also, in this case, I get the error
ModuleNotFoundError: No module named 'django_app'
Do you have any suggestion to solve this problem?
Thank you

What does admin.autodiscover actually do?

I've long been curious about what
admin.autodiscover()
actually do. The document didn't say much about it:
Above we used admin.autodiscover() to automatically load the INSTALLED_APPS admin.py modules.
and
There is really no need to use autodiscover when using your own AdminSite instance since you will likely be importing all the per-app admin.py modules in your myproject.admin module.
If I don't uncommnet
# admin.autodiscover()
what functionality I will lose?
And for what consideration should I use or not use autodiscover?
As u said: autodiscover() load all admin.py from the apps folders. So you have in the /admin/ all the models that you use (from your own app or not).
I recommend to use autodiscover() if you are going to use the admin app.
P.D. additionally some app have their on autodiscover with more functionalities.
admin.py is executed whenever your django loads URLconf from urls.py, the autodiscover() will search for all the apps in INSTALLED_APPS one by one and executes the code in that file.

Django application override & import path?

Let's have a django project using a 3rd party application.
I'd like to override some of its modules without touching original files.
Simple subclassing is not possible here, need to override code transparently as many other apps rely on original class names and functions.
Project's structure looks like:
django_project/
__init__.py
settings.py
overrides/ <-- here is a subdir with apps overrides
__init__.py
payment/ <-- here is an example of app to override
__init__.py
admin.py
forms.py <-- this file is ignored, original is imported
models.py
tests.py
views.py
settings.py was modified with
INSTALLED_APPS=(
'satchmo_store.shop'
#'payment' # original values
'overrides.payment' # modified app
...
)
The above solution however does not work, because Django does not insert path of added app into modules search path (sys.path).
Django just loads admin.py, models.py, tests.py and views.py, other files like forms.py are ignored.
Is this behaviour documented somewhere ? What exactly placing a module name in INSTALLED_APPS does behind scenes ?
I hacked the situation with hardcoding new modules search path in manage.py and Apache's setting of WSGIPythonPath.
import os.path
import sys
DIRNAME = os.path.dirname(__file__)
APPS_OVERRIDE = os.path.join(DIRNAME, 'overrides')
if not APPS_OVERRIDE in sys.path:
sys.path.insert(1, APPS_OVERRIDE)
I doubt this is the right way. Cann't find a guide describing apps overriding.
So, how can I properly override external Django application in my project ?
The bonus question: Do I need to copy whole application directory tree, not just particular files which are really modified ? As far as I know, Python stops at first matching module path, so it won't import other modules available in following parts of the search path.
Example of how to override your form:
overrides/payment/forms.py
from django import forms
class YourNewFormThingy(forms.Form): pass
overrides/payment/models.py
from satchmo.payment import forms as satchmo_payment_forms
from . import forms
satchmo_payment_forms.SomeForm = forms.YourNewFormThingy
Try including payment as well along with override.payment as satchmo uses payment module to process payments and payment code is flexible enough to include your code as well.

Is there any way to activate django admin site without admin.py

I have many apps and i want to activate the admin for all the models in my all apps.
I remember few months one of my friend did something that enables the admin site without any admin.py file
he did something in settings.py files with INSTALLED_APPS and all of the apps showed in the admin section
I am now not able to find that. Any one??
Your friend probably did something like...
from django.db.models import get_models
for model in get_models():
admin.site.register(model)
In one of his admin.py files.
I dunno, I'd only do this to test stuff. It's a bit too magical. Remember you'll have to explicitly unregister any models you may want to register again.
Just follow the instructions in the docs. They describe how to activate the django admin site here. You need to modify urls.py. That's it.
There are even comments in that file that tell you which three lines to uncomment.
I recommend you do include an admin.py in your apps because it is the Django convention and that some explicitness in what you trying to achieve is a good thing; the solution I use is the following default admin.py template for all new apps I start:
# Auto registers any new models with the admin, eventually you will want a tailored admin.py
from django.contrib import admin
current_app = models.get_app(__package__)
for model in models.get_models(current_app):
admin.site.register(model, admin.ModelAdmin)

How to resolve these Python errors in Django?

I'm trying to make my way through the Django Project's tutorial.
I've made it as far as this: https://docs.djangoproject.com/en/1.3/intro/tutorial02/#s-make-the-poll-app-modifiable-in-the-admin but I'm seeing errors in some of the files, e.g. in the admin.py file:
from polls.models import Poll
from django.contrib import admin
admin.site.register(Poll)
I'm getting the error
Unresolved import: Poll
The models are defined as outlined in the tutorial:
import datetime
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question
def was_published_today(self):
return self.pub_date.date() == datetime.date.today()
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length=200)
votes = models.IntegerField()
def __unicode__(self):
return self.choice
The tutorial states that when I restart the server after adding the admin file, I should see the Poll app referenced in the Admin page at 127.0.0.1:8000, but all I'm seeing is this:
I'm also seeing
Unresolved import: Poll admin.py /newProj/src/newProj/polls line 0 PyDev Problem
Unresolved import: settings manage.py /firstproject/firstproject line 10 PyDev Problem
Unresolved import: settings manage.py /newProj/src/newProj line 10 PyDev
Are the errors the reason why I wouldn't be seeing the Site administration page updated with the Polls app?
How can I resolve these errors?
/newProj/src/newProj/polls and /firstproject/firstproject... eeek, this looks to be honest like the source of a few problems. OK, a few concepts:
Python packages: All python applications can be comprised of packages. These are basically just directories containing a __init__.py file.
How python finds packages: Well, python can do one of two things when it looks for packages:
If the current directory is a package, i.e. contains __init__.py, it can import from files in it.
It can search on the python path (PYTHONPATH environment variable, or sys.path - same thing) and then down into sub packages.
How django projects are laid out: A default django project looks something like this:
project_folder/
__init__.py
settings.py # config
urls.py # url config
polls/
__init__.py # makes polls a package
models.py # models
admin.py # admin
views.py # app views
forms.py # per app forms
urls.py # per app urls
In this layout, there are two possibilities for your admin.py when you runserver:
from models import Poll - this works because you're remaining within the scope of your package.
from polls.models import Poll - works because polls is a package and so is the parent from where you're running runserver.
Although it's tempting, don't use project_folder as a package. It'll break the code as soon as you rename the dir (for example, during deployment).
So, with all that in mind:
verify your __init__.py files exist in the right places and that you're using a directory structure kinda like the one above. Might be best to check outside the IDE too - IDEs can be... difficult.
verify your path is searching where you think it is. The current directory should work just fine; if it isn't, you can see
import sys
print sys.path
will allow you to view where you're looking. You can explicitly add the current directory, but you shouldn't need to.
I don't like PyDev. Totally personal preference here, but I find it hard work, over and above the usual editor of choice + terminal + file browser. You might too, especially if you find the directory structure is radically different in your file browser as compared to what you think you have with the IDE.
You are using Pydev, which add an additional layer of abstraction on the importing process.
Use a light text editor and a console for learning. You can switch to an IDE once the Python Path and the import logic are clear enough in your head so you can setup Pydev yourself.
Are the errors the reason why I wouldn't be seeing the Site
administration page updated with the Polls app?
The answer to this question is in the same page, at https://docs.djangoproject.com/en/1.3/intro/tutorial02/#customize-the-admin-form
try this:
import newProj.poll.models

Categories