How to implement the add/edit links on a field in the admin change page that does not have an expressed FK relationship in the model? - django

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?

Related

Adding record of page views and details of change to django_admin_log

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.

How do we change Field Names in our existing Users table in django

I am trying to Edit Users Table in Django. I am using Users Table to login or register a users. I have to add a new field name Role in that Table but i can't find any option to edit that existing table in admin section.
i just try to field some files to field out where the code of that existing Table is but did't get it.
is there any way to Edit the Table or I have to Create a New Table and have to create a new method of registration.
i am not expert so it's hard to me understand things.
Well first, the Django admin interface it's just for performing CRUD operations over already existing models, you are not able to change in any way the database tables (at lest not using the "out of the box features") using the admin interface.
Said that in order to do what you want to do, with any model (not just User), you should:
Add the field to the model.
Instruct the admin interface to list this fields along the others.
Now the user model is kind of a special model here so I'll recommend a couple of readings you should complete before go forward with the model User customization.
References (User customization): Substituting a custom User model, Extending the User model.
And for the admin interface ...
Reference (admin interface): ModelAdmin options, special attention here to list_display

Adding a new section in Mezzanine CMS (Django) admin

I'm totally new to Mezzanine CMS. I got handed a site to work with and so far I've been able to do all the changes without problem. I've run across a problem in which they want a new section in the home page. I go to the admin section to edit the home page, but there is no extra content field.
On the home page, I see 4 sections "content" "priorities" "testimonials" and "clients". I would like to have another "content" area as a 5th section. How do I go on and add this section? I'm totally new to Django but would be appreciative if someone could explain or point in the right direction.
Here is a link to an image for reference.
https://imgur.com/a/sUKOtvS
Thanks in advance
The homepage content would be backed by a Django model with attributes for the partners and testimonial fields. You'll need to find the Python class for this model in your code base (you could search for those field names), and you'll need to add a new attribute for the new section you need.
Django and Mezzanine have lots of different field types you can use for these attributes, so consult their respective documentation for how those work (Django's are a lot more comprehensive, so start there).
Once you've done that, you'll need to create a database migration for the new attribute - that adds the field to the database table that will store the actual content, again consult the Django documentation for how these work.
Finally you may need to add the new field to the Admin class, which is the Python class (similar to the model) that controls which fields appear in the admin interface, and how they appear. I say "may" as these generally appear automatically without any code, but if things have been modified to a certain extent, you may need to do this manually.

Django Rest Framework Hyperlinked Fields Understanding

I can't seem to grasp the difference between HyperlinkedIdentity and HyperlinkedRelated Fields. I have a few questions that I can't seem to find the answers to online.
What is the actual difference? When would I want to use one vs. the other.
My next question is say I have 2 models, Project and Task.
A Task has a ForeignKey to Project. If I wanted the Project to hyperlink to the tasks within it, which Hyperlink field would I put in the ProjectSerializer? And what field would I put in the TaskSerializer to complement the ProjectSerializer assuming I wanted the tasks to be able to hyperlink back to the Project they are related to?
What is the difference between using the hyperlinked fields vs. just using regular nested serializers? When using hyperlinked fields, can I still filter by pk/id?
Last, What if a model had two hyperlinked relations in the serializer? From what I understand it creates a url field for each hyperlink, would it create two url fields in this case?
Thanks for any clarification you can offer, it will be a huge help towards cementing my understanding on the subject and allowing me to complete my API for my project.
What is the actual difference? When would I want to use one vs. the other.
HyperlinkedIdentityField is an hyperlink field for the current object itself while HyperlinkedRelatedField represent an hyperlink to other instances.
A Task has a ForeignKey to Project. If I wanted the Project to hyperlink to the tasks within it, which Hyperlink field would I put in the ProjectSerializer? And what field would I put in the TaskSerializer to complement the ProjectSerializer assuming I wanted the tasks to be able to hyperlink back to the Project they are related to?
HyperlinkedRelatedField is what you're looking for.
What is the difference between using the hyperlinked fields vs. just using regular nested serializers?
Hyperlinks can be browsed independently from the original resource. Handy if one of them belongs to another system. For example, you'll likely want to use hyperlink to tweets rather than let your server fetch them and them return them nested. Hyperlinks also allows the client to deal with its own caching rather than sending back all the data. Could be handy in case of fetching a list of items that nest the same user.
On the other hand, hyperlinks increase the network request count because it needs to fetch more data.
When using hyperlinked fields, can I still filter by pk/id?
Not sure what you mean here.
What if a model had two hyperlinked relations in the serializer? From what I understand it creates a url field for each hyperlink, would it create two url fields in this case?
Correct. hyperlinked relation are just a representation of a relation. It provides an hyperlink (an uri) to fetch the associated object.
This is useful because you won't need to know the pattern to fetch an object from the id: with a PrimaryKeyRelatedField you'll get the id but are missing the url to fetch the associated object.
This also allows the server to manage its own uri space without the need of updating the clients.
Hope this will help.

Django admin interface shows counts but no data

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.