I have been learning python for some months, and started tinkering with Django. Before posting this, I read up on the auto-generated 'admin.py'-code on github, as well as googled the matter. It appears my question is a little specific, and I was quite frankly very confused from that specific reading. Thus, I hope asking this adds value to this wonderful community. Question:
When connecting a model to the admin page, in admin.py, you first import admin:
from django.contrib import admin
After this, you import your model. Then, you supposedly connect your model through:
admin.site.register(MODEL)
What I do not understand is what 'site.register' is. The fact that the line starts off with 'admin.' makes perfect sense, as you are specifying from where the following import (ex. 'admin.function' or 'admin.class') comes from. Had it only been 'admin.somefunctionfromadmin' I would have totally understood this. Now, instead, I am confused as to what 'sites.register' is.
Is 'sites' a module, a file, and 'register' a function from within that module? If so, what does that make 'admin'? A package?
I have seen lines similar to these throughout Django, and feel a bit confused.
Thank you!
admin.site is the default instance of the AdminSite class. It is instantiated in django.contrib.admin.sites.
It is then imported in the django/contrib/admin/__init__.py. This makes it available as admin.site when you have done from django.contrib import admin.
When you call admin.site.register(Model), you are calling the register method of this admin site instance.
Related
I was following Django tutorial, and got stuck where it asked me to replace the default template for administrative part of the site with my own. The problem was a typo in the template's name. I suspected there must be a problem like that, but to troubleshoot the problem it'd be very helpful to see some kind of report from Django on what template it used to render a particular page. Is there any way to do this?
First if you have set DEBUG = True django automatically gives you information about where django was looking for templates (in general and especially in case it didn't find one)
You should see something like this:
second you can add the popular django plugin django-debug-toolbar. It can show you for each request what templates were used and what their context was.
see: https://django-debug-toolbar.readthedocs.io/en/stable/panels.html#template
Still, not exactly the answer, but something to get me closer. One could start Django shell, and then try this:
>>> from django.template.loader import get_template
>>> get_template('template/name').origin.name
to find out what template was actually used. This is still not enough to see though which templates were considered while resolving the template.
This is probably something simple, but I'm just not seeing it. So I started a new app called proposals. The following I entered into the app's models.py:
from django.db import models
class Proposal(models.Model):
name = models.CharField(max_length=200)
I then entered the following into admin.py:
from django.contrib import admin
from proposal.models import Proposal
class ProposalAdmin(admin.ModelAdmin):
pass
admin.site.register(Proposal, ProposalAdmin)
This seems incredibly straightforward, right out of the Django docs, but the "Add" and "Change" options for this admin are not appearing. They do appear for everything else, but not this particular admin. Any ideas on what might be causing this?
UPDATE
I'm continuing to check into this, and it's not a permission issue. The permissions are all set to true for add / change / delete. The template that generates the admin page requires a model.add_url for an "Add" link and model.admin_url for a "Change" link. These attributes are missing for some reason. Thus no links. Why they are missing is the big question.
UPDATE
I finally discovered what was going on here. An app which didn't need the add / change links was listed in the installed apps prior to this new one. Whatever it's author did to cause these links not to appear ended up being inherited by all other apps that followed it in this list. When I moved this new app above this one, the links appeared. I didn't even know that it was possible for apps to affect each other like this, but that is something to look for in the future.
First, I want to inform that I did check other related questions but their solutions were very simple (improper registration, settings, etc.). This problem is weird in a way that I haven't faced in 3+ years of developing with Django. So here comes:
I have an app that's 90% celery tasks, so it only has two models. They are simple. I have two ModelAdmin classes defined in the admin.py of the app, one for each model. These are simple as well. They are both registered properly. The app is in the INSTALLED_APPS.
All kosher and without any customization of templates, tags or forms, just a plain admin.py:
from myapp.models import (Something, OtherModel)
class SomethingAdmin(admin.ModelAdmin):
# admin config ...
class OtherModelAdmin(admin.ModelAdmin):
pass # Trying anything at this point...
admin.site.register(Something, SomethingAdmin)
admin.site.register(OtherModel, OtherModelAdmin)
So simple it cannot fail, but it does: one of them doesn't show up in the admin. It's simply not registered (404 on manual url access). The other one does show up, and does work properly.
Validation on that invisible admin works because when I add a strange value to its list_display, Django does raise the proper exception (ImproperlyConfigured). So it does reads it, it just fails to register it. If I comment the visible one out, the app is simply removed from the admin (of course, it thinks no modeladmins).
So, in short, one of the ModelAdmins is invisible, while the other one in the same file and with nearly identical configuration, isn't. Any thoughts?
EDIT: Answers to a few suggestions I expect: Yes, the model is working properly (and heavily unit tested), and I have created/saved instances and they are in the db. Yes, I did restart the server. Yes, the computer is plugged in and it's currently on. :)
As it turns out, the problem was in the structure: models was a package, instead of the more usual module. It seems that even if you make the model available at package level (import it in init.py), Django still doesn't know in what app it should be included.
What you need to do is specify the app_label in its Meta class. So the model now becomes:
from django.db import models
class OtherModel(models.Model):
class Meta:
app_label = 'someapp'
# other meta attrs
# Model attrs ...
Odd that it needs to be specified, when the model is available in the usual models.SomeModel namespace, but at least the solution's simple enough.
BTW, as you can guess the other model did include this Meta attr, I just didn't notice it before. LOL.
EDIT: I'm new to this site but if you are going to down vote me, could you perhaps explain why? I've searched Google, this site and others but have not found anything that makes any sense and I thought this was a site to ask questions and get some help.
I've got a Custom PHP Forum that I am trying to convert to Python/Django as a learning experience and I'm having some problems. I've been reading up on Django and it is encouraged that our application is split into multiple apps. I went through the 6 part tutorial and many other parts of the documentation but I'm left with some questions.
Let's assume that I have about 30 tables.
Tables such as:
posts_index, posts, users, user_groups, user_activity, user_sessions, forums, payment_gateways, payment_logs, etc for a basic forum
I'm having issues structuring my models. With PHP all I needed was index.php, /admin/index.php, view_forum.php, view_thread.php and a few others, everything could pull directly from the database and I had no issues but now I have to deal with apps/modules.
I'm thinking I'd need to structure my apps in a manner similar to this:
/admin/ app
/forums/ app
/view_forum/ app
/view_thread/ app
/forums/view_forum/ app (instead of just /view_forum/, could be a sub app)
/forums/view_thread/ app (instead of /view_thread/, could be a sub app)
My problem and only question here is dealing with global state. For example Users/Group/Session/Logging/Permission information is going to need to be shared across multiple apps through importing in the other apps models file. To do this I need to reference their model information, what is the correct way to handle this?
Would either of these be acceptable?
Create a ton of different apps such as /users/ which would model my users_groups, users, user_sessions, another app for /posts/ that would include models for posts_index, forums, and so forth with these models existing but not actually being used publicly, they would be used in other apps only. They would be imported in areas such as the /view_forum/ app since when viewing a forum I might need to determine if the user is logged in, is a member of a particular group, etc and because of that would need access to a number of the hidden apps and hence would be imported from the hidden app.
What if I just had one single app, instead of it being an app it would just be my entire project. This sounds like the best solution to me but it seems to be suggested if we cannot summarize the entire application into a sentence it needs to be broken up. If I went with one single app being used as my entire project, my models file will have 30+ different models, is this acceptable? I assume not but figured I'd ask.
Do either of the above make any sense? If not what would you do fix it? I'll admit I'm lost so any feedback would mean a lot.
I'm new to Python/Django and am trying to figure things out. I hope I am clear on what I am trying to do. I'm more than welcome to any advice. I've been trying to play around with things but I figure it would be better to ask for advice from more experienced developers. I'm not a professional programmer and am still learning so please be nice :).
I have voted this up... I had similar questions when I first moved to Django (also coming from PHP)
Try not to think of apps in terms of db tables (or url paths), you want to create apps for independent pieces of functionality.
I would say most of your code will be in a single forum app with Forum and Post models in it and all your forum-related urls like /view_forum/ and /view_thread/. Note there's not really such thing as a sub-app in Django... these are different views which all belong to one related set of functionality in a single app.
The 'users' stuff... you normally want to hook in to the Django auth system (https://docs.djangoproject.com/en/dev/topics/auth/default/#user-objects) though if you are trying to keep the legacy database structure this may be harder... you may end up needing your own users app.
The payment gateways stuff sounds like another app again.
For the admin, you get this (almost) for free with Django:
https://docs.djangoproject.com/en/1.5/ref/contrib/admin/
You need an admin.py inside each app, where you register the models that you want to expose to the admin site.
You might find it's best to follow a tutorial and build a simple blog (or try and build a very simple minimal forum from scratch) to get a feel for Django before tackling your re-write. Because trying to exactly recreate the old functionality with legacy db tables will be a bit harder and may lead you into patterns which are not 'good Django'.
You might also find it useful to look at the source code of an existing Django forum app, such as this one:
https://bitbucket.org/slav0nic/djangobb/src/
They have just a single djangobb_forum app that does everything. I think this is entirely justified as a forum is a single complicated piece of functionality.
Note how their Profile model effectively extends the built-in Django auth.User model via a OneToOneField. It makes it easier to integrate with the built-in login and authentication system that way.
Start by integrating your legacy database and then build the Admin site. You'll see how the model information is available to the Admin app and every other app you write. The key is to import models in your apps.
Does anyone have experience (Django 1.x pref 1.3) with implementing a sort of singleton accessible from the admin page to expose some global variables for editing (site name, keywords, ...).
I cant find anything like this and it sounds quite unbelievable!
thanks
(django-preferences is broken with 1.x)
As lazerscience says, you probably want Django-dbsettings. I have a fork at Github that works with the latest Django versions.
after some playing I had dbsettings working... but with a few glitches:
- Aptana doesnt recognise the import preferences as a valid reference
- when I access my /settings/ page with the fields of the model I created and then save it I have a CSRF token missing or incorrect. error
NOTE: The official googlecode repository doesnt work (with 1.3), Daniel's version does instead (I guess he changed newforms -> forms etc). The way I created a new model for the settings veiw is:
from django.db import models
import dbsettings
class ImageLimits(dbsettings.Group):
maximum_width = dbsettings.PositiveIntegerValue()
maximum_height = dbsettings.PositiveIntegerValue()
options = ImageLimits()
You should avoid using singleton's as much as possible.
Are Singletons really that bad?
What is so bad about singletons?
For the rest, site name is editable in Django admin (see django.contrib.sites module).
Talking about keywords - it's bad to repeat them, thus, you better implement it in your item model (page, news article, etc).
Could you maybe give more examples of what do you need it for?