I'm using Django 1.4 and experiencing an unusual problem with hidden rows in my admin site.
I can view individual models in my app, and they appear to be querying the database correctly when I click into each one; I can see the number of matches in the top left corner ("3 locations" below my actions bar, for example). However, entries do not appear below that count.
If I try to open an entry directly using the URL, I also get a blank page.
I haven't customized the templates or css. Anyone have experience with this type of problem?
Update: if foreign keys are removed in the model, the entries reappear below the counts. However, that FK field is needed so still trying to identify the root cause.
Fixed. This appears to happen when the model uses a ForeignKey field, and the table it points to does not have its data loaded. That accounts for the model seeing the number of rows, but not being able to pull up the individual entries.
I had this same issue (i.e. I could see the model count in the admin, but not the actual records).
I have a model (Category) with a ForeignKey to another model (Competition). I looked in the database and somewhere along the line while doing some code refactoring on the models and migrations, I ended up with the FKs on the Categories pointing to a non-existent Competition.
When I updated these FKs in the database, the records reappeared in the admin.
In admin.py where you use foreign key you have to add at the last _id for example my foreign key I'd is iClientId so in admin.py we have to write in list_display iClientId_id.
Related
I have a Django 3.x web site. There are 3 models, among others, Document, MetaData, MetaDataValue. The MetaDataValue model has a foreign key relationship to the MetaData model.
In a simple world, there would be a foreign key relationship from MetaData to Document. Then the DocumentAdmin would display the MetaData field as a dropdown, filled with the appropriate MetaDataValues. There would also be edit/add (pencil/plus) links next to the dropdown to allow the user to edit/add the MetaDataValue for that MetaData object.
However, one of the requirements for the project was not to define which, or how many, MetaData objects would be associated with a particular Document type until run time. Those associations are through another set of models. Therefore, the Document admin change page adds the different MetaData fields to the change admin page at run time, by looking into the database for which MetaData fields are associated with this type of Document, and then adding them to the fieldset through the get_fieldsets method.
The implication of this design is that one cannot edit/add values to a particular MetaData field on the Document admin change page, because, I assume, Django lost the underlying foreign key relationship between the Document and MetaData models because the fieldset is generated in the admin's get_fieldsets method.
I could add pages of code to show how the MetaData fields are generated at run time, but I don't think that would make the description any clearer. I have looked at the page source and fieldsets generated for the "simple world" example described above above, and cannot see where Django is figuring out when to add the edit/change links to the drop down for a particular foreign key field.
My question, is how can I add the pencil and plus sign to these MetaData fields displayed in the Document admin change page, and give the user to option to add/edit the MetaDataValue for that particular MetaData object? I could just create some Ajax calls and do all the heavy lifting myself, bu I would prefer to leverage as much of the Django infrastructure as possible, and not reinvent more than I have to.
Thanks!
Mark
I found a solution using the RelatedFieldWidgetWrapper. I added this widget wrapper to all my selects that needed the green plus (add) and yellow pencil (edit).
There is too much code to post here, but here is the meat of it. My db table MetaData has the names of all the fields, and MetaDataValue has the values for each metadata field. The metadata is used to describe a document (text, video, image), but there are no FK relationships between the MetaData model and the Document model. The relationship between the metadata and the documents is contained in a JSON field in another table. The MetaData table also has what type of Django field is used for that metadata field. There is also another table that determines which metadata fields apply to which document type (image, text, video). For all the ModelChoiceFields, I add the field and the widget (Select wrapped in a RelatedFieldWidgetWrapper).
elif (metadata_names[i].field_type == MetaData.MODELCHOICEFIELD):
fields[metadata_names[i].name] = forms.ModelChoiceField(queryset=MetaDataValue.objects.filter(metadata_id=metadata_names[i].metadata_id).order_by('value'), required=False, label=metadata_names[i].label, help_text=metadata_names[i].help_text)
# add the green plus (add) and pencil (edit) links to each select field
fields[metadata_names[i].name].widget = RelatedFieldWidgetWrapper(fields[metadata_names[i].name].widget, MetaDataValue._meta.get_field('tag_value'), admin_site, can_add_related=True, can_change_related=True)
if 'documentType_id' in fields:
# Editing/add a new document type seems like a bad idea, as document type is used a lot in the processing logic
fields['documentType_id'].widget.can_add_related = False
fields['documentType_id'].widget.can_change_related = False
The hard part was getting the right arguments for the RelatedFieldWidgetWrapper. The documentation is a little sparse on that widget, because, I think, it was an early part of the admin, but much of the Django code has changed since it was first implemented, so a lot of ways this wrapper was used in the past (ie stack overflow posts) has been deprecated. I just looked at the source, and tried what seemed to be appropriate until it worked. Finally, these articles helped a lot:
RelatedFieldWidgetWrapper
More RelatedFieldWidgetWrapper – My Very Own Popup
How can I remove the add and change buttons from a TabularInline admin field?
Is it possible to register a dummy model (Does not exist in db) that will display data from multiple models in one page?
Maybe just list all objects and when use click on one, a new webpage is opened with details of the clicked on objects? Which is usually this view:
admin:{app_name}/{model_name}/{object_id}/change
The closest standard solution to what you want are Django inlines:
https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#using-generic-relations-as-an-inline
I fail to see how you could create a model not present in the db.
We are using LogEntry/django_admin_log and recording additions, changes and deletions made from Django Admin. However we have two issues we need to address:
1.) Changes record only the field that changed. Not the old and new values. We would like to add the specific details of all changes.
2.) We would like to record an action in this log every time a page is viewed on the Django Admin panel.
How would it be best to proceed?
We are happy to do some work to extend the existing functionality of this, or we are happy to move to a completely new 3rd part module if necessary, or write our own. But would like some guidance from some experts?
We had similar requirements in terms of keeping history and track of actions done by users with a higher level of detail in terms of values changes. What we ended up doing was creating a new model called "History" which we populated with the user, the name of the model being changed, the instance id and a dictionary called changes showing the name of each field changed and values from - to.
In order to populate the new model, we overrode the save_model function in the admin file for the model we want to track. Regarding the page views, you can overrride the get_fields if "obj" is not None and create an instance of History accordingly.
I have a model Sessions that contains almost 10,000 objects. Each session has a foreign key relationship to a Subject. The problem is that when loading a page that has a foreign key field to a session, the page takes a long time to load.
To fix this, I like to have an admin on which you select a subject from one ForeignKey field, and have the sessions that have a relationship with that subject appear in a second ForeignKey field.
Is this something that is possible from within the django admin interface? I have checked out django-smart-selects (though I'm unsure if that would actually do what I'd like it to), but when I try to import it I get an error "No module named admin_static", which I believe may be because I'm using an outdated version of Django (v 1.1).
Any help would be appreciated. Thanks.
Are you sure you don't just need raw_id_fields?
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.raw_id_fields
When you visit an admin change form that has a foreign key to Sessions it will build a select dropdown with 10,000 entries. This is probably your slowdown.
Say I have an app with ModelA, ModelB, and ModelC
For my app's admin page (/admin/app), how do I hook into the display of the "App administration" page so I may hide Model types that are empty (have no instances)?
That's a big ask, because you'd have to dynamically register/unregister apps according to the results of a database/ORM query (a count(), at least) for each of the models that each of the INSTALLED_APPS contains.
Every single time you viewed the admin.
While that in itself is unpleasant enough, bear in mind that admin.py for each app is processed at server restart/reload time (IIRC), so you could't hope to hook up something cute like those DB lookups there, as it'd only get run once and not reflect the actual state of models currently have objects stored in your database.
Better move: leave it be. If there are no objects to view for a given model, then there are no objects to view for a given model.
If you're concerned about your client/user making new models in there when they shouldn't, then that's a combination of user education and admin user permissions that you can sort out.
As said in a few places: "The Admin is not your app." If the customization goes beyond the trivial, it's time to write your own views. You can still hook them in to the admin site by overriding the base admin template and even serving them from the same root path as the rest of your admin.