admin site doesn't show object fields - django

I have a model with a PointField from django.contrib.gis.db.models . This somehow doesn't let the admin site show the objects with a nice table of fields and values. Instead it displays one field named after the model name. The values are just a bunch of ' object'. With the name of the model. If I click the object I can edit it fine. It would be nice however to be able to filter and see the field values at the admin/ page itself.

Since PointField does not have a __unicode__ attribute, for the proper name to show up, you can register a new admin model object.
Now, in the admin's list_display,
class PointFieldAdmin(admin.ModelAdmin):
list_display = ('name', 'field_x', 'field_y', ...)
admin.register(PointField, PointFieldAdmin)
More on admin models registering here

Related

Django admin for categories and objects

I have objects and catetories in Django and object has ForeignKey to Category.
In Admin user must first create categories and then create objects choosing category from list.
What I want to have is file manager metaphore: User opens list of categories, clicks "create object here" and creates one like we do it with folders and files.
I wonder if Django has some application for it. Does it?
I know about inlines, but I do not want to edit object on the same page, I want to have list of them.
It is similar to Django: adding an "Add new" button for a ForeignKey in a ModelForm but I do not have ModelForm, I speak about admin
In Django admin, you can use inlines, example:
class OBJECTSInline(admin.TabularInline):
model = OBJECTS
extra = 0
class CATEGORYAdmin(admin.ModelAdmin):
list_per_page = 10
inlines = [OBJECTSInline,]
admin.site.register(CATEGORY, CATEGORYAdmin)
If you register both your models in the Django admin, you will see that when creating/editing an object with foreign key to Category, there will be a dropdown for the foreign key value, which lists existing values, and next to it, buttons for editing/deleting the selected value, or for creating a new Category:
That seems to be what you're asking for - it's already there in the admin as soon as you register the relevant models.

Django Admin ForeignKey field widget options and inconsistent defaults

I have a model that has foreign keys, and in the admin those FKs render as drop-down lists. However, some of them show buttons for 'add', 'edit', and 'delete' of the elements in the related table, and others do not. I cannot figure out what is different between the fields such that some render one way and some render a different way.
My ideal situation is that those buttons do not render for any foreign keys, that editing one model is restricted to just changes on that entity itself.
I see that Django ultimately selects the RelatedFieldWidgetWrapper for these fields. I can set can_add_related, can_change_related, and can_delete_related on this widget, but I don't see how to easily pass these as options for these fields so that they are all consistent.
How do I manage turning these options on and off in the admin?
New a staff user(not superuser) in admin,assume model A has foreignkey named model B,assign add/change/delete perms of model A and add perm of model B to that user,use that user to login admin,you can and only can add model B in admin panel or RelatedFieldWidgetWrapper.Because can_xxx_related is cal in admin by perms by:
wrapper_kwargs.update(
can_add_related=related_modeladmin.has_add_permission(request),
can_change_related=related_modeladmin.has_change_permission(request),
can_delete_related=related_modeladmin.has_delete_permission(request),
)
code in django\contrib\admin\options.py\line 162

Replace foreign key dropdown with textbox with add/edit icon - Django

Related to foreign key fields in the Django Admin, the default display
element is a drop down list box containing all of the foreign key
items from the related model. I my app it will contain thousands of items and I am looking to change the admin interface and have it use a text box instead of the populated drop down.
Looking for textbox with add/edit icon next to it, so that we dont get populated values, we just directly add or edit.
Is there any way around to achieve it.
What you are looking for is raw_id_fields
class ArticleAdmin(admin.ModelAdmin):
raw_id_fields = ("newspaper", )
By default, Django’s admin uses a select-box interface (<select>)
for fields that are ForeignKey. Sometimes you don’t want to incur
the overhead of having to select all the related instances to display
in the drop-down.
raw_id_fields is a list of fields you would like to change into an
Input widget for either a ForeignKey or ManyToManyField:
NOTE: The raw_id_fields Input widget should contain a primary key if the field is a ForeignKey or a comma separated list of values if the field is a ManyToManyField. The raw_id_fields widget shows a magnifying glass button next to the field which allows users to search for and select a value:
You can read the docs here
You can try use custom Form and realize custom Widget on this form field. (I use for this desicion 3rd party library django_select2)
from django import forms
from django_select2.forms import ModelSelect2Widget
class KeyWidget(ModelSelect2Widget):
model = ModelToKey
search_fields = ['field__icontains']
def label_from_instance(self, obj):
return u'{}'.format(obj.field)
class CustomForm(forms.ModelForm):
class Meta:
model = ModelWithKey
fields = ('foreign_key_field')
widgets = {
'foreign_key_field': KeyWidget(attrs={'style': 'width:550px'}),
}
In also you can overload Form __init__ for customize queryset of objects for choosing in this field.

Django admin inlines on default list page?

I have a table that only has a handful of entries in it, and it'd be nice if I could use inlines for their list instead of forcing staff to click through to the edit page each time.
That is, when someone clicks on the link that ordinarily gives a list of the model objects, they should instead see the model objects displayed inline.
I tried something like this, but unsurprisingly it gives an error because there's no foreign key:
class MyModelInline(admin.StackedInline):
model = MyModel
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyModelInline,]
admin.site.register(MyModel, MyModelAdmin)
For it to work as you've described you'll need an "editor" model to be a parent for the data. All the rows you want to display should have a foreign key to a single 'editor' model object. So, in models.py:
from django.db import models
class Editor(models.Model):
pass
class MyModel(models.Model):
name = models.CharField(max_length=100) # Field added for demonstration
# ... add any other fields you like ...
editor = models.ForeignKey(Editor)
And in admin.py:
from django.contrib import admin
from Test.models import Editor, MyModel
class MyModelInline(admin.StackedInline):
model = MyModel
class EditorAdmin(admin.ModelAdmin):
inlines = [MyModelInline,]
admin.site.register(Editor, EditorAdmin)
Some other things to consider:
When you make a new MyModel() object programmatically you must always set the foreign key to point to the editor. There should only be one instance of the editor for this to work as you've described. When using the admin interface, this foreign key should be set automatically by using the admin page for the editor object. I would suggest restricting creation and deletion of editor objects for everyone except yourself in production. If someone deletes the editor object then all MyModel objects disappear as well.
Alternative options:
1) If the edits the admin staff is doing are simple then I would recommend implementing "actions" instead.
2) There's also the possibility of overriding the admin template. I personally like this option less because every time Django is updated I have to check that my changes aren't interfering with new features. However, sometimes this is the only way to do some more advanced things in the admin interface. I've done this in my own project, but like to keep the changes minimal.

display one-to-many relationship for a model in Django admin (list mode)

In Django admin site, when listing all the objects for a given model, I know we can customize which columns get displayed for a ModelA via list_display
Say that ModelA has a one-to-many relationship with ModelB. I would like to add another column on the listing page for ModelA, where each entry is a URL pointing to all objects of ModelB having a foreign key relationship on corresponding instance of Model A in that row. How can I achieve this customization with the admin app?
you should add a method to ModelA's admin class:
def modelb_link(self, inst):
url = u'../modelb/?modela__id__exact=%d' % inst.id
return u'Models B' % url
modelb_link.allow_tags = True
modelb_link.short_description = u'Models B'
In the url the 'modela__id__exact' part is a filter for list page, where 'modela' is the name of ForeignKey field, in ModelB class, that links to ModelA.
Then use this method in 'list_display' property and you are done. If you encounter any problems, just ask, I'll try to help.
Greetings,
Lukasz