How can I adjust the appearance of the Django Admin? - django

Kindly help me How can i customize the text&charfield(length,breadth,font,colour) without using templates for the following code
class Record(models.Model):
Name = models.CharField(max_length=200,blank=True,null=True,help_text="Employee Name")
Empid = models.CharField(max_length=300,blank=True,null=True,help_text="Employee ID")
Salary = models.IntegerField(blank=True,null=True)
Bonus = models.IntegerField(blank=True,null=True)

In your admin.py:
class RecordAdmin(admin.ModelAdmin):
# your stuff...
class Media:
css = {
"all": ("my_styles.css",)
}
Documentation for class Media.
Now you should be able to override what you want in the my_styles.css file.
If you want a more general solution (not only for Record model but for many models), a good way to do it is to extend the base_site.html template to add your own CSS file to all admin pages.
{% block blockbots %}
<link rel="stylesheet" type="text/css" href="/media/css/admin_base.css" />
{{ block.super }}
{% endblock %}
I put it in blockbots instead of extrastyle to be sure it will be at the end so it will override all other stylesheets.
Documentation on overriding/extending admin templates.

It is not possible to modify the visual elements of the Django admin from the model. This would totally defeat the purpose of an MVC framework! Separation of concerns dictates that these changes would be done in the template.
If you want to change the text size you'll have to modify the stylesheets for the admin.

Maybe you need to create Forms from your Models and to customize them, here is the oficial doc.
Use widgets to customize with HTML attributes

Related

How are Django's form assets (Media class) served?

The "Form Assets" page of Django says
Django allows you to associate different files – like stylesheets and scripts – with the forms and widgets that require those assets. For example, if you want to use a calendar to render DateFields, you can define a custom Calendar widget. This widget can then be associated with the CSS and JavaScript that is required to render the calendar. When the Calendar widget is used on a form, Django is able to identify the CSS and JavaScript files that are required, and provide the list of file names in a form suitable for inclusion on your web page.
Okay, but what component of Django takes those form assets and actually puts them in the page?
I ask because I'm trying to use django-autocomplete-light (DAL) with django-bootstrap5 on a multi-select form with a many-to-many field. I've done all the installing, put the widget on my form field:
class SomeForm(forms.ModelForm):
class Meta:
model = Something
fields = ['things']
widgets = {
'things': autocomplete.ModelSelect2Multiple(
url='myapp:things-autocomplete')
}
I know the widget url is correct because if it's wrong, Django barks. I know the widget is being put onto the field because it changes (from listing all things to a blank square).
I can see the HTML for the form widget includes autocomplete-light stuff to multi-select "things" with "things" autocomplete:
...
<select name="things" class="form-select" required id="id_things"
data-autocomplete-light-language="en"
data-autocomplete-light-url="/things-autocomplete/"
data-autocomplete-light-function="select2" multiple>
</select>
...
However, I don't see anywhere that select2.js is included in this web page.
I used django-autocomplete-light's ModelSelect2Multiple, which has the Select2WidgetMixin that defines a media property with all kinds of good looking stuff:
return forms.Media(
js=(
'admin/js/vendor/select2/select2.full.js',
'autocomplete_light/autocomplete_light%s.js' % extra,
'autocomplete_light/select2%s.js' % extra,
) + i18n_file,
css={
'screen': (
'admin/css/vendor/select2/select2%s.css' % extra,
'admin/css/autocomplete.css',
'autocomplete_light/select2.css',
),
},
)
I do not see any of that good-looking stuff in my web page.
I'm running with debug=True (dev mode) for now, so I believe that static files should be served as long as I have the django.contrib.staticfiles app in my settings, which I do.
Which Django component should be serving up DAL's media, and how?
I'm using Django 4.1, django-autocomplete-light 3.9.4, django-bootstrap5 22.2.
P.S. I saw other questions that seemed related, but not exactly this situation.
EDIT: It looks like form assets are loaded in a template with {{form.media}}. Maybe I have to put that media in the right place (the HTML head)?
I got this to work by adding a script block, and adding jquery and the form media manually:
{% block head_script %}
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
{{form.media}}
{% endblock head_script %}
Not sure if there's a more automatic way to include widget media.

Using placeholder tags in non-django CMS pages

In the Django CMS there's the {% placeholder 'content' %}. I tried to use it on a non-django-cms page, i.e., a detail-view page that comes from an apphook. However, when I switch to the structure view in the detail-view page and the placeholder does not seem to reflect. Is that's how it's supposed to work or is there a problem with my code? If it's how it's supposed to work is there a way to make placeholder appear in the page?
You can't use {% placeholder outside of CMS pages.
If you're on one of these pages, you can use a static placeholder. These will show the same content on any page where a static placeholder with the same name exists. So a good example of these is a footer, or header where you'd want it to be the same on all pages;
{% static_placeholder "footer" %}
Another thing you can use, good for your example of a detail page in an apphook, is a PlaceholderField on your models.
Take this example;
from django.db import models
from cms.models.fields import PlaceholderField
class Category(models.Model):
name = models.CharField(max_length=20)
description = PlaceholderField('category_description')
In your template you can then render this placeholder and it'll behave like a standard placeholder on a cms page;
{% load cms_tags %}
{% render_placeholder category_instance.description language 'en' %}
You can find docs for PlaceholderField here

Django admin dashboard, is there a way to lowercase model name?

I'm looking for a way to lowercase the first letter of a model in my django admin site.
i.e.:
model verbose name is "agent-1.0.0" is shown as "Agent-1.0.0" on the dashboard,
simple but IDK
grappelli trick will also work for me.
django - 1.7.1
also - need this only for one app models group - not all of my dashboard should be lowercase...
so, overriding the index.html is not so efficient
The capitalization is hard-coded in the template, same for the templates in Grappelli.
You can use catavaran's suggestion, but this will transform every model name. Overriding the template is a huge pain in the ass to maintain for something this small.
The only workable solution I can think of is to bypass the capfirst filter with a space:
class Meta:
verbose_name = " agent-1.0.0"
As capfirst only forcibly capitalizes the first character, nothing will happen if the first character is not a letter.
Model name passed to template as capfirst(model._meta.verbose_name_plural) so you have to lowercase it in the admin/index.html tempate or via CSS. Imho CSS option is simpler:
div.module tr[class^=model-] th {
text-transform: lowercase;
}
If you want lowercase only some models (for example User) then change CSS selector to this:
div.module tr.model-user th {
text-transform: lowercase;
}
With Grapelli you could create a custom Dashboard by running:
python manage.py customdashboard
and setting GRAPPELLI_INDEX_DASHBOARD on your settings to your custom class.
You can make this custom class extend from the Dashboard class that grappelli offers and override it to your needs. Look especially at the ModelList class, where you can specify the title you want for the model.
There is a CSS-way for those who don't want to override Django admin classes. Override and extend templates/admin/base_site.html template as follows:
{% extends "admin/base_site.html" %}
{% block extrahead %}
<style>
h1.model-title {text-transform: lowercase;}
h1.model-title:first-letter {text-transform: uppercase;}
</style>
{% endblock %}
{% block content_title %}
{% if title %}<h1 class="model-title">{{ title }}</h1>{% endif %}
{% endblock %}
This will make only first letter of each content_title uppercase.
You can use the same way to lowercase model name in admin tables as well as sidebar. However, I'd like to point that by tacit agreement model's verbose_name as well as verbose_name_plural shouldn't be capitalized. This will save you a lot of overrides in your project, like I provided above to normalize change_list header.

Django : Customizable templates

I am working on creating a web portal and I want to offer the users the feature of making changes to there profile/dashboard like changed background. etc.
Can anybody please guide me to an efficient approach to achieve this?
Thanks
This is trickery that has more to do with css and javascript than with django templates.
The only thing that is django related here is the actual storing of these preferences.
e.g. the filepaths of the actual background images.
After that you will do something similar to what is described in this answer:
how to change html background dynamically
EDIT
I don't see why you need different directories for every user. Django templates
give you more than enough power to do what you want.
For example, let's say that each user can upload his own background picture. Also
I assume that you follow this popular django pattern for storing additional information
about your users. https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
So we have this UserProfile model:
class UserProfile(models.Model):
CHOICES = (
('vertical', 'Vertical'),
('horizontal', 'Horizontal'),
)
user = models.OneToOneField(User)
background_image = models.ImageField(upload_to='images')
dashboard_layout = models.CharField(max_length=10, choices=CHOICES)
You can pass this extra information to your javascript context(either with Ajax or without)
and then change the background image for every individual user.
Also we could do special layout at the template level like this:
{% extends "base.html" %}
{% block main_body %}
{% if request.user.get_profile.dashboard_layout == 'vertical' %}
{% include "layouts/vertical.html" %}
{% else %}
{% include "layouts/horizontal.html" %}
{% endif %}
{% endblock main_body %}

How to give a column in the Django admin change_list a CSS class

I'd like to change the column widths in the list display of the Django admin.
Is it possible somehow to add a CSS classname to a column?
I'd preferably not overwrite the entire template to accomplish this.
In Django >= 1.6, CSS classes are included with list_display output:
"The field names in list_display will also appear as CSS classes in the HTML output, in the form of column-<field_name> on each <th> element. This can be used to set column widths in a CSS file."
While this feature is implemented in vers1.6 as StvnW said, for earlier versions you can do the following:
In admin.py:
class MyModelAdmin(admin.ModelAdmin):
# your code here
# specify a stylesheet just for the list view
class Media:
css = {'all': ('css/mymodel_list.css')}
In mymodel_list.css:
/* replace '5' with the column desired */
table#result_list td:nth-child(5) {
width: 15em;
}
Specifying table#result_list will apply this stylesheet only to the list view and won't affect the normal admin page for this model. Also, note that while django uses th for the first column of the model, it still counts for a td child.
There is an open ticket that addresses the need for specifying css classes for table columns in the change_list view.
That said ... in the description for the ticket there's a snippet that injects a custom stylesheet in your change_list-template:
{% extends "admin/change_list.html" %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="/css/poll_admin_changelist.css" />
{% endblock extrastyle %}
So you don't override the whole template, only the part (extrastyle) you need.
Now you could inject your own stylesheet and for example style your columns using the :nth-child-selector
Another option would be to wrap your specific fields in html which can be done using the list_display option. Here you could define a width or class for a wrapped element.
This does only makes sense though, if you want to control the width of limited set of fields