Django - Admin custom field display & behavior - python

Let's imagine this model:
class ScribPart(models.Model):
name = models.CharField(max_length=50, unique=True)
text = models.TextField()
I'd like to attach a specific class to the field text and call a specific js file. So that the admin page would be like:
...
<script type="text/javascript" src="/static/js/mymarkup.js"></script>
...
<textarea id="id_text" name="text" class="mymarkup"></textarea>
...
How can I do that with a widget and/or custom admin form ?

To insert a <script> in an admin page the simplest thing to do is:
class ScribPartAdmin(model.ModelAdmin):
...
your normal stuff...
...
class Media:
js = ('/path/to/your/file.js',)
ModelAdmin media definitions documentation
Now to add the class attribute to the textarea I think the simplest way to do it is like this:
from django import forms
class ScribPartAdmin(model.ModelAdmin):
...
your normal stuff...
...
class Meta:
widgets = {'text': forms.Textarea(attrs={'class': 'mymarkup'})}
Overriding the default widgets documentation
I should add that this approach is good for a one shot use. If you want to reuse your field or JS many times, there's better ways to do it (custom widget for the field, with JS file specified if the JS is exclusively related to the field, extending template to include a JS file at many places).

You have to create a template, put it in templates/admin/change_form_scribpart.html with this content:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block content %}
<script type="text/javascript" src="/static/js/mymarkup.js"></script>
{{ block.super }}
{% endblock %}
Also, don't forget to activate this new admin template in your ScribPart ModelAdmin:
class ScribPartAdmin(admin.ModelAdmin):
ordering = ...
fieldsets = ...
change_form_template = "admin/change_form_scribpart.html"

You can send your form with json pack and get(check) with this code
results = ScribPart.all()
for r in results :
if r.test == id_text:
self.response.out.write("<script type='text/javascript' src='/static/js/"+r.name+"mymarkup.js'></script>")

Related

How to add script type="module" in django admin

If I want some javascript functionality in my Django admin, I usually go about it using the Media class like this:
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ('js/my_script.js',)
But I now have a script that is a ES6 module so I would like Django to render it like:
<script src="path/to/static/js/my_script" type="module"></script>
and using the Media class doesn't render the type="module" attribute.
Any help or tips to achieve this? Thanks
You won't be able to use Media class for this, if you check at the code, the method will always render the same type="text/javascript".
If you really want to go with the Media way, you could create your own Mediaclass and inherit from forms.Media, then you could try using Media as a dynamic property that would be able to generate a script with type="module".
Another option is to use a custom template as suggested before, or even considering adding a templatetag to your app in order to add ES6 modules in your template.
In your custom change_form.html template, extend the admin_change_form_document_ready block and add the event listener code
{% extends 'admin/change_form.html' %}
{% load static %}
{% block admin_change_form_document_ready %}
{{ block.super }}
<script type="text/javascript" src="{% static 'app/your_file.js' %}"></script>
{% endblock %}
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
class Media:
module = ('js/my_script.js',)
You can just change js to replace module its define is type of src
It‘s working for me.

Filename only in django form field

I have a model that contains a filefield and am using a modelform to add instances. When I come to modify an instance the form shows the current file and displays the file path ie library/filename.
Is there a way to show just the filename in the form?
Thanks
I got around this by using javascript.
I added the following to my model..
def filename(self):
return os.path.basename(self.file.name)
Then added this into my javascript in my template
{% block javascript %}
<script>
{% if part.file %}
$('[href="{{ part.file.url }}"]').html("{{ part.filename }}");
{% endif %}
</script>
{% endblock %}
This changed the link to show just the filename
A FileField will use by default the FileInput widget that produces a <input type="file"> HTML tag. I don't think you can change the default "display full path" behaviour from Django, check this post.
However, you can customise things in your ModelForm like that:
class YourForm(ModelForm):
class Meta:
...
widgets = {
'your_file_attribute': FileInput(attrs={'html_attribute': value}),
}

Adding css/js files to the home site in the admin's panel django

I am trying to add a simple script to my admin's panel in django. I am following this example from the doc, which works when I do this:
class ArticleAdmin(admin.ModelAdmin):
class Media:
js = ("my_code.js",)
admin.site.register(Article, ArticleAdmin)
my_code.js (which lives in STATICFILES_DIRS) gets executed when I open the "Article" link in the admin's panel (so this would be the example url: localhost:8000/admin/news/article/)
However, I want it to be executed in the home site, as in right after I login to the admin's panel (this would be the url:localhost:8000/admin/) . Where do I have to insert the class Media then?
Are you trying to make your custom javascript appear on all admin pages? Then the best thing to do is to override the default admin templatte.
Look in your django installation and find django/contrib/admin/templates/admin/base.html make a copy of it in templates/admin in your project folder. Then simply add the following to the html.
<script scr="my_code.js" type="text/javascript"></script>
Then the js will be available on all admin pages.
I found another way which is overriding instead of replacing as explained in here.
If you place the file base.html into templates/admin:
{% extends "admin/base.html" %}
{% load static %}
{% block footer %}
{{ block.super }}
<script type="text/javascript" src="{% static 'my_code.js' %}"></script>
{% endblock %}
This will insert the script after the footer in the at localhost:8000/admin/.
Here I am "overriding" the base.html. But since I am using .super (explained here) it adds the script after the footer tag.

Google map Autocompletion in Django Admin Add form

I have a model which uses source and destination fields and these are usually populated from a frontend template. Template has two form fields which are associated with Google map autocomplete APIs. But if I want to create a new object through admin panel, how can I integrate autocomplete API with add form's source and destination fields?
You can easily use something like https://github.com/ubilabs/geocomplete/ in django admin —
Override the change form template to include the required js:
{% load staticfiles %}
{% block extrahead %}{{ block.super }}
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/geocomplete/1.4/jquery.geocomplete.min.js"></script>
<script src="{% static 'path/to/your/js/geocomplete.js' %}"></script>
{% endblock %}
In your own js file:
$("#address_input").geocomplete();
Docs here on how to populate form using the library:
https://github.com/ubilabs/geocomplete/#populate-form-data
There is Django admin widget called django-location-field that does exactly what you ask. I use it in my projects.
https://github.com/caioariede/django-location-field

Django AdminModel add_view prepopulated fields

I have a simple model being displayed in the admin. In the add view I have 4 fields, with the first field being a foreign key to user. I need to:
Pre-populate the user field.
Make the field read only.
I cannot find any documentation on this. I looked at the following links:
django admin "add page" initial datetime from GET parameters,
Customize Django Admin: Add More Than One Default Inline on Parent Add_View
EDIT:
I found a solution for my first problem here; Djanjo admin: Prefill data when clicking the add-another button next to a ForeignKey dropdown
Here, you need to add jQuery for prepopulate that particular field. Create your own js script file inside static directory of your app & just extend change_form.html of admin site. For example if you want add script.js script into your add template, your extended change_form.html will look like as follows:
{% extends 'admin/change_form.html' %}
{% load static %}
{% block admin_change_form_document_ready %}
{{ block.super }}
<script type="text/javascript" src="{% static 'qb/js/formset_handlers.js' %}"></script>
{% endblock %}

Categories

Resources