34

I have an object which I want to use under admin instead of a model which inherits models.Model. If I make it inherit models.Model, this object will create a table in the database which i don't want. I only want this object to stay in memory.

One solution I have come with help from the nice people at stack overflow is I create admin views, register these custom views via a modelAdmin ( admin.site.register() ) under admin.py and use this model-like object as dynamic data storage (in memory).

Since this model like object doesn't inherit from models.Model, admin.site.register() (under admin.py) doesnt accept it and shows a 'type' object is not iterable" error when I try to access it in the browser.

sysasa
  • 913
  • 1
  • 9
  • 16
  • You can hook extra views up to a particular model (and do whatever you want to in them, related to the model or not; I can post an answer with this solution if you like), but I don't know of any way to create a purely standalone admin view, outside of hacking the admin source. – eternicode Nov 10 '10 at 21:19
  • @eternicode actually it's perfectly possible to create standalone admin views: see my answer. – Daniel Roseman Nov 10 '10 at 22:09
  • @Daniel Roseman, ah, so! I've never seen that functionality before, though TBH I've never needed it yet. – eternicode Nov 10 '10 at 22:20

3 Answers3

26

hmmm. Thanks for your help everyone. The solution I have come up ( with your help ofcourse :) is as follows:

I have two custom templates:

   my_model_list.html
   my_model_detail.html

Under views.py:

class MyModel(object):
    # ... Access other models
    # ... process / normalise data 
    # ... store data

@staff_member_required
def my_model_list_view(request) #show list of all objects
    #. . . create objects of MyModel . . .
    #. . . call their processing methods . . .
    #. . . store in context variable . . . 
    r = render_to_response('admin/myapp/my_model_list.html', context, RequestContext(request))
    return HttpResponse(r)

@staff_member_required
def my_model_detail_view(request, row_id) # Shows one row (all values in the object) in detail     
    #. . . create object of MyModel . . .
    #. . . call it's methods . . .
    #. . . store in context variable . . . 
    r = render_to_response('admin/myapp/my_model_detail.html', context, RequestContext(request))
    return HttpResponse(r)

Under the main django urls.py:

urlpatterns = patterns( 
    '',
    (r'^admin/myapp/mymodel/$', my_model_list_view),
    (r'^admin/myapp/mymodel/(\d+)/$', my_model_detail_view),
    ( r'^admin/', include( admin.site.urls ) )
)
sysasa
  • 913
  • 1
  • 9
  • 16
  • 1
    Glad you figured this out on your own. I was just about to comment the same. An admin view without a model is basically just a normal Django view using an admin template with a mock ModelAdmin instance, which is basically what you're doing. I've done this myself to create some custom admin-themed pages. – Cerin Dec 27 '13 at 16:31
8

You can add your views directly to the AdminSite object, rather than to any particular ModelAdmin subclass which you then register.

The default AdminSite is accessed via django.contrib.admin.site, which is what you call register and autodiscover on. Instead of using this, you could create your own subclass and add your own views to it, and then register your models against that rather than the default one.

philshem
  • 24,761
  • 8
  • 61
  • 127
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Interesting; I'm assuming these subclasses are picked up by the one `autodiscover` call? Or does your subclass need to be used across the entire site's apps to be effective? (Actually, I feel like I'm not grasping the concept properly...) – eternicode Nov 10 '10 at 22:26
  • Thanks for your help Daniel! Solution posted below, though not entirely sure this is what you meant. Anyways, it works ! :) – sysasa Nov 11 '10 at 15:25
5

The most straightforward answer is "no". As the Django Book says, the admin is for "Trusted users editing structured content," in this case the structured content being models arranged in hierarchies and configured through settings.py. More importantly, if your object doesn't completely duck-type to a models.Model complete with expected relationships, the admin will probably toss exceptions all over the place.

However, as the mantra goes, "It's just python." You can override any of the pages in admin. Just create your own templates in your project, and have them come first in the template search. Also, by inheriting admin/base.html, you maintain the look & feel of the administration project.

Write your administrative view and templates for this object, just like any others, but making sure to wrap the views in the is_staff decorator to ensure that the views are protected from access by unauthorized users. Put those in the application, perhaps in admin/views.py, with templates/admin/object_list.html and object_form.html.

Once you have appropriate administrative tools for these non-database objects, you can then provide access to them through the administration index page: You want to override admin/index.html, and provide additional project-specific items to the page as needed.

I have done exactly this to provide administrative access to third-party APIs that store our data, such as the ConstantContact email service, and it works pretty well.

Elf Sternberg
  • 16,129
  • 6
  • 60
  • 68
  • Thanks for your help Elf. I've posted my solution answer below, though Im not sure if Ive exactly followed your advice. – sysasa Nov 11 '10 at 15:24