How to access model data when overriding Django admin templates? - django

sorry if this is an obvious question but I have been searching for a few days and have not been able to come up with a result.
I am creating a simple photo gallery app. There are four galleries, each containing a photo (the photo consists of a 'before' image, 'after' image and caption). I am trying to use django-admin to allow users to click on a gallery and then add photos.
I am using a TabularInline to edit the photos within each gallery. In addition to the default columns on the TabularInline, I would like to add a column that shows a thumbnail preview of the 'before' photo and 'after' photo (I am using easy-thumbnails for this). After much searching, it seems like the best way to do this is to override the django-admin tabularInline.html template and add the column myself - so I created another copy and am trying to edit it now.
What I would like to do is simply reference the Photo object within the Django admin template that I am overriding - but I don't know the appropriate tag to use. I need the reference so I can use it in conjunction with the easy-thumbnails thumbnail tag ... but for the life of me I cannot figure out the template tag that references the object. I have tried iterating through the ModelForm, FormSet, and FieldSet objects but none seem to give me a direct reference to the object.
# models.py
class Gallery(models.Model):
name = models.CharField(max_length=200)
url = models.CharField(max_length=200)
desc = models.TextField()
def __unicode__(self):
return self.name
class Photo(models.Model):
gallery = models.ForeignKey(Gallery)
before = models.ImageField(upload_to='gallery')
after = models.ImageField(upload_to='gallery')
caption = models.CharField(max_length=1000)
order = models.IntegerField(blank = True, null = True)
def __unicode__(self):
return "Photo " + str(self.order)
# admin.py
class GalleryForm(forms.ModelForm):
model = Gallery
class Media:
js = (
'/assets/js/jquery-1.4.2.min.js',
'/assets/js/jquery-ui-1.8.2.custom.min-admin-sortable.js',
'/assets/js/menu-sort.js',
)
class PhotoInline(admin.TabularInline):
model = Photo
extra = 1
template = "admin/tabular-thumbnails.html"
admin.site.register(Gallery,
inlines=[PhotoInline],
form = GalleryForm)
Thanks so much in advance and please let me know if there's any additional information I can offer. I am using Django 1.1

In Django 2.1 {{adminform.form.instance.field_name}} worked for me.

{{ form.instance }} will always be the model instance associated with a modelform, assuming there is one.
(Note that ``{{ formset.instance }}` is the instance of the parent model in an inline formset).

Related

Trouble displaying inline forms of a ModelAdmin

I am encountering what seems to me a weird bug when rendering Inline forms on the "Add" view of a ModelAdmin.
Here is a minimum example with Django version 2.2.4.
in models.py:
class MyModel(models.Model):
text = models.CharField(max_length=100)
class RelatedModel(models.Model):
parent = models.ForeignKey(MyModel, null=False, on_delete=models.CASCADE)
number = models.DecimalField(decimal_places=2, max_digits=10, null=False, blank=False)
in admin.py:
class RelatedModelInlineTabular(admin.TabularInline):
model = RelatedModel
show_change_link = False
fields = ("number", )
class TestMyModelCreate(admin.ModelAdmin):
fields = ['text', ]
inlines = [RelatedModelInlineTabular]
admin.site.register(MyModel, TestMyModelCreate)
Steps to replicate
Login to django admin website
open the "add" view for MyModel (i.e. navigate to the list of Models and click on the "Add new" button)
Expected result
The form displays an empty text field. Below that, an Inline form is displayed with 3 empty rows for potential related instances of RelatedModel
Actual result
The Inline form is displayed twice, each instance with its own 3 empty rows, as if I had specified it twice.
I attach a screenshot below of the actual page (Discount is the name of the related Model). I tried and I get the same result with both StackedInline and TabularInline.
Am I making some trivial error here that could explain what's happening? Or is this is a known bug? Thank you in advance to anyone that will help.

django admin foreign key to file field and many to many field

I have a model Teacher which has following data:
class Teacher(models.Model):
name = models.CharField(max_length=100)
thumbnail = models.ForeignKey(Thumbnail)
class Thumbnail(models.Model):
thumbnail = models.FileField(upload_to=upload_to)
class TeacherAdmin(admin.ModelAdmin):
list_display = ('name',)
Here I want to relate all the thumbnail in my project to Thumbnail field. In my admin it shows me a dropdown of thumbnail while I want to add the thumbnail from admin.
Is it possible that I can upload from admin too?
Also what can I do in the case like :
class Teacher(models.Model):
name = models.CharField(max_length=100)
thumbnail = models.ManyToManyField(Thumbnail)
If I want to add multiple Images.
The only issue I am having is on admin side. Client side can be handles from regular forms.
Need suggestions and Ideas

How can I dynamically change list of fields displayed in admin interface depending on the choice in the first field?

I want the admin interface to show disctrict field only if I choose 'B' as the category. If I choose 'W' I want all fields of Offer model to be displayed. Is it possible to show selected (filtered) fields in admin page depending on the choice in other field in the same model? Thanks in advance for your help.
My models:
class Category(models.Model):
NAME_CHOICES = (
('B', 'BLACK'),
('W', 'WHITE'),
)
name = models.CharField(max_length=200, choices=NAME_CHOICES)
class Meta:
verbose_name_plural = 'Categories'
def __unicode__(self):
return self.get_name_display()
class Offer(models.Model):
category = models.ForeignKey(Category, verbose_name='Kategoria')
city = models.CharField(max_length=128, verbose_name='Miasto')
province = models.CharField(max_length=3)
district = models.CharField(max_length=128, verbose_name='Dzielnica')
def __unicode__(self):
return "Offer number %s" % (self.id)
First of all I must to tell, that django works only in sync way. So if you want to choose which input to use, you must send a request and wait a feedback. In my opinion there're no straight way to do this task correctly.
And I see a few solutions:
1) You can use jQuery for that. But the main problem is that django has a own admin system with a built-in widgets. You can try to customize it in two ways:
Take an app with this option (for example, django-admin-tools) and create custom behavior on your form;
manage.py collectstatic and after that going to admin folder and create custom jQuery script.
2) Build a custom admin form for your model with ModelChoiceField. I don't quit sure about this field behavior really help you, but you can investigate that.
If I need to do this task, I choose first way with admin static and custom jQuery.

Django Admin Select Objects based on ManyToMany Relationship

I'm working on building a django app that extends the Mezzanine project. Mezzanine has a Gallery app (photos). I'd like to create "portfolio" page that acts as a landing page which has a single image and link to each gallery page.
Each gallery (Gallery) can have multiple images (GalleryImage). I'd like to via the admin select a gallery, then select an image to be displayed. However, I can't seem to figure out what to do.
Here's my model:
class GalleriesThumb(models.Model):
relatedlandingpage = models.ForeignKey(LandingPage)
relatedgallery = models.ForeignKey(Galleries)
thumb = models.ManyToManyField(GalleryImage)
def __unicode__(self):
return self.name
class Galleries(models.Model):
landingpage = models.ForeignKey(LandingPage)
tagline = models.CharField(max_length=100)
galleries = models.ManyToManyField(Gallery)
def __unicode__(self):
return self.name
class LandingPage(models.Model):
gallerytitle = models.CharField(max_length=200)
def __unicode__(self):
return self.name
My admin is something like:
class GalleryInline(admin.InlineModelAdmin)
model = Galleries
model = GalleriesThumb
list_display = galleries
list_display = thumb
class LangingPageAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('gallerytitle')
})
inlines = [GalleryInline,]
I realized that this won't do what i want, but how do I get the list_display on the the images that are related to Galleries. I'm pretty sure it needs to be a method, or am I taking a completing wrong approach if the selections that are made will be defining the content on the page. (I realize that I'm also missing my fields to store the selection in.)
I'm sorry if this a dumb question, but this my first real world attempt an app.
I think this link will resolve your problem
Django 1.2.1 Inline Admin for Many To Many Fields
class GalleryInline(admin.InlineModelAdmin)
model = Galleries.galleries.through

Django admin TabularInline - is there a good way of adding a custom html column?

I've got a model (Entry) which contains a simple property:
#property
def image(self):
return str(self.id)+"_"+self.round.season.name+"_"+self.round.theme+"_"+self.person.name
I use this to build the name of a particular image file on disk. So I know that there's going to be an image at /path/to/images/(model.image()).jpg
I can display the raw image property itself within the TabularInline layout on an admin page by adding it to the readonly_fields collection, but how would I go about getting a column which had custom html wrapped around the model property?
e.g.
<img src="/images/{{model.image}}.jpg" />
What you can do is create a method in your TabularInline subclass that returns the HTML you want, then use that method's name in place of image in ImageInline.fields:
from django.utils.safestring import mark_safe
class ImageInline(admin.TabularInline):
...
fields = (..., 'render_image')
readonly_fields = (..., 'render_image')
def render_image(self, obj):
return mark_safe("""<img src="/images/%s.jpg" />""" % obj.image)
According to current Django 1.2+ I got errors "Form does not have such field as render_image". Solution is simple put the render_image function into model.Admin not in your inline form, second thing is fields and readonly_fields settings in your Inline form... So here You have what I've ended up with:
class OfferPropertyInline(admin.TabularInline):
model = OfferProperty
fields=('property_value',)
readonly_fields = ('property_value',)
class OfferAdmin(admin.ModelAdmin):
inlines = [
OfferPropertyInline
]
def property_value(self,obj):
return obj.get_value()
admin.site.register(Offer, OfferAdmin)
Lechup's answer does not work for me, I am using Django 1.11.7. I found this way to work around.
Let say I have 2 tables: Campaign and Article, one campaign has many articles. I want to show the articles when browsing a specific campaign.
Table Article has a column named score, which is a float. I want to round it up to 2 decimal places when viewing in Django admin.
This example shows how you can make a custom column for TabularInline in Django admin.
class Article(models.Model):
title = models.TextField(null=False)
url = models.TextField()
score = models.FloatField(null=True)
def __str__(self):
return self.title
def display_score(self):
if self.score:
return round(self.score, 2)
return self.score
display_score.short_description = 'Score'
class ArticleInline(admin.TabularInline):
model = Article
readonly_fields = ('title', 'url', 'display_score')
fields = ('title', 'url', 'display_score')
class CampaignAdmin(admin.ModelAdmin):
inlines = [ArticleInline]
admin.site.register(Campaign, CampaignAdmin)
#lechup correct except you need:
readonly_fields = ('mycustomfield',)
defined in the Inline for later versions of django (+1.4)