Imagekit as a foreignkey - adding an image in admin - django

This relates to adding information in a Foreignkey field in the main admin screen.
I have a Staff model. I need mugshots in 3 formats. I'd like to use django-imagekit for processing.
I've made a Photo model to store the mugshot, and added it as a Foreignkey to Staff as photo = models.ForeignKey(Photo).
Question: How can I add the mugshot directly in the Staff admin screen, i.e. avoid having to upload the mugshots separately in their own admin screen then link to them from Staff?
Thank you for your thoughts ...

Depends on what screen you need it in, but I guess you need it in the details/edit screen?
The most simple method is creating a template in your app, called:
/templates/admin//staff/change_form.html
In this template place the following:
{% extends 'admin/change_form.html' %}
{% block content %}
{% if not add and original.photo %}
<img src="{{original.photo.url}}" alt="Photo" />
{% endif %}
{{ block.super }}
{% endblock %}
This places the image above the rest of the content if in edit modus (so no image in add mode).
If you need it in the list you can add a custom function to your admin.py as well returning the HTML snippet for showing the photo.

Related

Include google analytics tag to django admin without changing the template for every page

Is there a way to include the google-analytics javascript snippet easily into the django admin page ? (django 1.10)
I would like to do that without creating a custom template for each of the admin page, just insert the script in the all admin.
Thank you,
You need to override the base admin page and put the tag there. Inside Template Directory, create a folder name admin, inside that, create a base_site.html. That base_site.html might look like this:
{% extends 'admin/base_site.html' %}
{% load static %}
{% block extrahead %}{{ block.super }} google analytics codes {% endblock %}

Django tabular inline display

Is it possible to change the display of inlines in order to change it to this? I was thinking of changing the admin template file "tabular.html", is it going to be possible or should I change something else?
Update
Ok, I've been trying to edit the tabular.html but my experience with Django isn't enough to understand how/where to make the necessary changes... Any clue of where I should start?
Shouldn't I be changing the CSS also?
I guess that {{ field.field }} automatically renders the dropdown menu (Django admin default) if I'm understand this correctly...
Update 2
I was able to change the second column to the functionality that I wanted but I think that for the first one it's going to be trickier... Current status
Update 3
One hack that I think would work is to display on each of the inlines only one of the options of the first field and then deactivate the "add another option". How can I iterate on the options in "tabular.html" ?
Update 4
I guess the trick should be done here... How can I iterate on the field choices in order to display only one choice per line?
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{{ field.get_choices_display }}
<td class="{{ field.field.name }}">
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{{ field.field.errors.as_ul }}
{{ field.field }}
{% endif %}
</td>
{% endfor %}
{% endfor %}
{% endfor %}
Yes, you could change template of your InlineModelAdmin instance to your customized template, for example customized_inline.html. Simply copy django/django/contrib/admin/templates/admin/edit_inline/tabular.html to customized_inline.html in your template path as starting.
edit
Perhaps I was misunderstanding. If you want to change the rendering style of a form field, the normal way is to change its widget. In Django ModelAdmin and InlineModelAdmin, the main ways of customizing a field widget goes around BaseModelAdmin.formfield_for_dbfield method inside django/contrib/admin/options.py, reading the code and the doc when you want to change the widget of a form field.
For field having choices, you could simply set radio_fields in ModelAdmin/InlineModelAdmin instance to render the field as radio select instead of dropdown.
Furthermore, use OneToOneField instead of ForeignKey, or set extra and max_num in your InlineModelAdmin instance to prevent admin from rendering multiple rows of inline, like:
class SomeInlineAdmin(admin.TabularInline):
model = Foo
extra = 1
max_num = 1
I cannot open your second link, you could post things in the question instead of using a external link.

Accessing Many to Many relationship in Django

I have set up a few models as follows:
Page
Gallery
Image
Gallery and Image share a many to many relationship.
Page can have 1 or 0 galleries.
I have created a gallery with a few images and attached it to a page object.
However, I'm having trouble displaying it in a template.
Can anyone help?
My page view looks like this:
def detail(request, page_id):
p = get_object_or_404(Page, pk=page_id)
return render_to_response('page/detail.html', {'page': p},
context_instance=RequestContext(request))
And the template:
{% block images %}
{% if page.gallery %}
{% for image in page.gallery.image_set.all %}
<a rel="gallery" href="{{ STATIC_URL }}{{ image.image }}"></a>
{% endfor %}
{% endif %}
{% endblock %}`
If I try to output some text within the IF block it comes out OK but not within the loop.
Any advice on getting it to work / generally tidying this up would be greatly appreciated.
Thanks.
If the Gallery-Image relationship is many to many I'm guessing you have an m2m field on your Gallery model, where the m2m manager is the field itself. The manager can be queried just like any other QuerySet: model_instance.mym2mfield.filter().
If your ManyToManyField is called images on the Gallery model, your template would look like this:
{% for image in page.gallery.images.all %}
<a rel="gallery" href="{{ STATIC_URL }}{{ image.image }}"></a>
{% endfor %}
If your ManyToManyField is on your Image model, the default name would be as you describe, unless you specified a related_name in which case you'd use that name.
{% for image in page.gallery.image_set.all %}
Your problem may lie in the way you're accessing the gallery from the page. In your template, try something like the following and see if you get any output:
{{ page.gallery }}
There are instances where certain errors may get ignored in a template.
Also, I'm a little curious how your Page and Gallery are related? Does the Page model have a OneToOneField called "gallery"? Does Gallery have a ForeignKey to Page? In the latter case, you'd access the galleries associated with a page by:
{{ page.gallery_set.all }}
It would be easier to answer this question if you provided some additional information about the fields on your models.

Django, Pulling a Value from a Model based on an ID

I'm relatively new to Django and as a test of my knowledge I'm trying to set up a project where it displays a list of games between anchor tags, when one of the game tags is clicked on, it pulls information about that game from a model using the ID (primary key) relative to that name. For instance the first games ID would be 1 and so on.
However, I am uncertain as to how to approach building a view for this. The only way I was able to get information from a template before was from user input (input tag) and then using request.GET to take the information from the input.
So far in this project, anchor tags are linking to a different URL which has the view which gets the information based on the id, then it should refresh the page and the information should display. Everything should be easy, but I'm just having trouble thinking of a way to get the id of the game based on which link is clicked. Is there a way I can simply set the value of this ID somewhere and reference it in the view, or rather pull the id of the game based on which link is clicked?
Code:
{% extends "base.html" %} <!-- Extends the base models html design-->
{% block title %}Arcade{% endblock %}
{% block content %}
{% if games %}
<p>Found {{ games|length }} game{{ games|pluralize }}</p>
{% for game in games %}
<li>{{ game.game_name }}</li><!--Game Link->
{% endfor %}
{% else %}
<p>There are currently no games in the database.</p>
{% endif %}
{% if results %}
{% endif %}
{% endblock %}
I hope I did an adequate job explaining this problem.
To simplify it further: How do I pull any kind of value from a template?
Thank You
Keith
This is simple. In each iteration of your for loop, you have an object called game, which is presumably a model instance. So you can just do:
<li>{{ game.game_name }}</li>
Or, even better, use the reverse URL functionality:
<li>{{ game.game_name }}</li>
You should look at using AJAX for this.
When the user clicks a tag, have the page asynchronously GET or POST to your django backend. If you want to GET, write a url to the effect of
^/data/game/(\d+)
then grab the id, get your model instance, and return some json or xml.

Django admin: adding pagination links in list of objects to top

Is it possible to have the pagination links that appear at the bottom of a list of objects in Django's admin interface at the top as well?
Can this be done without changing the admin templates? I suspect not, given the lack of a ModelAdmin option, but thought I'd see if anyone had done this before I dug into the template code.
I really, really don't want to have to copy and paste change_list.html into a new file, just so I can add a pagination line - that'll make changing Django versions painful, since I'll have to check if anything's changed in that file, and re-apply my change.
Do not copy change_list.html, instead create a new template that extends it:
{% extends "admin/change_list.html" %}
{% block result_list %}
{% block pagination %} {{ block.super }} {% endblock %} <!-- pagination -->
{{ block.super }} <!-- rest of results list -->
{% endblock %}
Then pass the new template's name to ModelAdmin in change_list_template attribute - doc here.
The source code implementing the django admin template for change_list.html has a content block so if you create a file change_list.html under 'admin' folder in your templates directory and add this:
{% extends "admin/change_list.html" %}
{# added pagination to top as well as bottom #}
{% block content %}{% pagination cl %}{{ block.super }}{% endblock %}
it should do the trick!