Addition of css class on widget file input has no effect - django

Try to add a css class into a forms.ImageField, has no effect.
model.py:-
class ProductImages(models.Model):
...
image_file_w200_png = models.ImageField(
verbose_name = "Imagens",
upload_to=upload_to_image_file_w200_png,
null=True,
blank=True,
default='magickhat-profile.jpg'
)
...
forms.py:-
class ProductImagesForm(ModelForm):
image_file_w200_png = forms.ImageField(widget=forms.FileInput(attrs={'class': 'image_add_product'}))
class Meta:
model = ProductImages
fields = ['image_file_w200_png']
That code has no effect, what is missing?
Edit:
admin.py
class UsersAdminSite(admin.AdminSite):
site_header = 'Painel Administrativo'
index_title = 'Painel Administrativo'
kadmin = UsersAdminSite(name='kadmin')
class AdminProductImages(admin.TabularInline):
model = ProductImages
extra = 1
max_num = 10
list_display = ('image_file_w200_png',)
fieldsets = (
(None, {'fields': ('image_file_w200_png',)}),
)
add_fieldsets = (
(None, {
'fields': ( 'image_file_w200_png'),
}),
)
kadmin.register(User, UserAdmin)
kadmin.register(Product, AdminProductModel)

Change the name of your image_file = forms.ImageField() to be image_file_w200_png. What you are doing there currently is defining a new field rather than changing your existing field because the names are not the same.
You could also define it in a different way in your class Meta: section. You can add a dictionary called widgets and write it like this:
class Meta:
model = ProductImages
fields = ['image_file_w200_png']
widgets = {'image_file_w200_png':forms.FileInput(attrs={'class':'image_add_product'})}
Edit:
The original poster was trying to add a css class to their admin.TabularInline class in their admin.py file. This can be done by using the same form definition above in my answer and specifying in the admin.TabularInline class what form is used. Example:
class ModelInline(admin.TabularInline):
model = #Model Class Name Here
form = #Form class Name Here

Related

How to add a calculated field to a django admin inline

I am trying to add a calculated field to a Django Admin Inline. Consider this set of classes:
models.py:
class MyGroup(models.Model):
group_name = models.CharField()
size = models.IntegerField()
class MyUser(models.Model):
user_name = models.CharField()
groups = models.ManyToMany(MyGroup, related_name="users", through=MyMembership)
class MyMembership(models.Model):
group = models.ForeignKey(MyGroup)
user = models.ForeignKey(MyUser)
timestamp = models.DateTimeField(auto_add_now=True)
I want to show the group.size field in the inline. I thought the following code would work (based on this answer):
admin.py:
class MyMembershipInline(admin.TabularInline):
model = MyUser.groups.through
fields = (
"group",
"timestamp",
"size",
)
readonly_fields = (
"timestamp",
"size",
)
def size(self, instance):
return instance.group.size
#admin.register(MyUser):
class MyUserAdmin(admin.ModelAdmin)
fields = ("user_name",)
inlines = (MyMembershipInline,)
But I am getting the following error:
Unknown field(s) (size) specified for MyMembership
Any advice?
While looking for a solution to this problem, I found a solution that worked for me at the following URL:
https://www.boris.co/2013/04/computed-field-on-tabularinline.html
The example given is:
class StatsInline(admin.TabularInline):
model = Stats
fields = ('clicked', 'shown', 'avg')
readonly_fields = ('avg',)
verbose_name = 'Stats'
verbose_name_plural = 'Stats'
can_delete = False
def avg(self, obj):
return float(obj.clicked) / obj.shown if obj.shown else 0
The calculated field needs to be provided in both the fields and readonly_fields attributes.
I wound up having to use a custom ModelForm in the inline. I did it like this:
admin.py:
class MyMembershipInlineForm(forms.ModelForm):
class Meta:
model = MyUser.groups.through
fields = ("group", )
readonly_fields = (
"timestamp",
"size",
)
size = forms.IntegerField(disabled=True)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
my_membership = self.instance
self.initial = {
"size": my_membership.group.size if my_membership.pk else None
}
class MyMembershipInline(admin.TabularInline):
model = MyUser.groups.through
fields = (
"group",
"timestamp",
"size",
)
form = MyMembershipInlineForm
#admin.register(MyUser):
class MyUserAdmin(admin.ModelAdmin)
fields = ("user_name",)
inlines = (MyMembershipInline,)

Django Serialize multiple models in a single view

Here's the scenario, i have two models Offre and Recruteur
class Recruteur(models.Model):
[...]
entrepriseName = models.CharField(max_length=50)
[...]
class Offre(models.Model):
[...]
idRecruteur = models.ForeignKey(Recruteur,verbose_name = "idRecruteur", on_delete=models.CASCADE, default=None)
[...]
And I have the following serializers:
class RecruteurByIdSerializer(serializers.ModelSerializer):
class Meta:
model = Recruteur
fields = ( 'entrepriseName',)
class OffreSerializer(serializers.ModelSerializer):
recruteur = RecruteurByIdSerializer(many=True, read_only=True)
class Meta:
model = Offre
fields = ( 'title', 'dateAjout', 'description', 'recruteur')
i expected this result:
but im getting this instead:
what am i doing wrong ?
You have to provide source parameter as below,
class OffreSerializer(serializers.ModelSerializer):
entrepriseName = RecruteurByIdSerializer(source='idRecruteur', read_only=True)
class Meta:
model = Offre
fields = ('title', 'dateAjout', 'description', 'entrepriseName')

django-polymorphic-tree serializer

I would like to serialize all the nodes in my PolymorphicMPTTModel with their corresponding fields. Following the documentation django-polymorphic and django-mptt i get this:
{
"count":1,
"next":null,
"previous":null,
"results":[
{
"title":"Submenu",
"subcategories":[
{
"title":"Plato1",
"subcategories":[
]
},enter code here
{
"title":"Plato2",
"subcategories":[
]
}
]
}
]
}
The structure is fine, but the fields of the children are missing.
Models:
class Menu(PolymorphicMPTTModel):
parent = PolymorphicTreeForeignKey('self', blank=True, null=True, related_name='children', verbose_name='parent')
title = models.CharField("Title", max_length=200)
class SubMenu(Menu):
titulo = models.CharField("Titulo", max_length=200,default="not defined")
class Plato(Menu):
titulo = models.CharField("Titulo",max_length=200,default="not defined")
descripcion = models.TextField()
ingredientes = JSONField()
precio = models.PositiveSmallIntegerField(default=0)
# Extra settings:
can_have_children = False
Serializers:
class PlatoSerializer(serializers.ModelSerializer):
class Meta:
model = Plato
fields = ('titulo', 'descripcion', 'ingredientes', 'precio')
class SubMenuSerializer(serializers.ModelSerializer):
class Meta:
model = SubMenu
fields = ('titulo',)
class MenuItemModuleSerializer(serializers.ModelSerializer):
subcategories = serializers.ListSerializer(source="children",child=RecursiveField())
class Meta:
model = Menu
fields = ('title','subcategories')
View:
class MenuView(viewsets.ModelViewSet):
queryset = Menu.objects.all()
queryset = queryset.toplevel()
serializer_class = MenuItemModuleSerializer
I know I'm kinda late to the party but I had the same issue and finally found a solution that is working for me.
As django-rest-polymorphic states, you need a mapping between models and serializers:
class ProjectPolymorphicSerializer(PolymorphicSerializer):
model_serializer_mapping = {
Menu: MenuItemModuleSerializer,
SubMenu: SubMenuSerializer,
Plato: PlatoSerializer
}
Your RecursiveField() creates a serializer instance from its parent class. That makes all your child objects using the MenuItemModuleSerializer and thus missing child fields.
Every child needs to get mapped to its serializer using ProjectPolymorphicSerializer
RecursiveField(to='ProjectPolymorphicSerializer')
Change your MenuItemModuleSerializer to this:
class MenuItemModuleSerializer(serializers.ModelSerializer):
subcategories = serializers.ListSerializer(source="children", child=RecursiveField(to='ProjectPolymorphicSerializer'))
class Meta:
model = Menu
fields = ('title','subcategories')

Django admin: list not correct (duplicate rows)

My admin.py is like this:
class ResizableAdmin(admin.ModelAdmin):
class Media:
css = {
}
js = ('js/vendor/jquery-1.11.2.min.js',)
class GroupeMotsForm(django.forms.ModelForm):
mots = django.forms.ModelMultipleChoiceField(
queryset=Mot.objects.all().order_by('groupes__description', 'texte'),
widget=django.forms.SelectMultiple(attrs={'class': 'resize_dst'})
)
class Meta:
model = GroupeMots
fields = ['description', 'admin_taille_fenetre', 'mots', ]
widgets = {
'admin_taille_fenetre': django.forms.NumberInput(
attrs={'class': 'resize_src'}
)
}
class GroupeMotsAdmin(ResizableAdmin):
form = GroupeMotsForm
In my database I have only one row in GroupeMots:
It's displayed 3 times in the list of the admin interface:
Any idea where to look? Where could Django look to have 3 results? They all point to the same record. I'm stuck.
My model is like that:
class GroupeMots(models.Model):
description = models.CharField(max_length=150)
mots = models.ManyToManyField(Mot, blank=True)
class Meta:
ordering = ['mots__texte']
def __str__(self):
return u'{0}'.format(
self.description
)
And the problem came from ordering = ['mots__texte'] because there seems to be 3 results, so "ordering" generates dupes... I changed it to description and now it's ok

Django Many to Many Inline - how to show fields referenced by through model?

I'm trying to customize and many to many inline in the django Admin, but I'm not able to display the fields of the underlying models.
Here's a simplified example. Maybe you can tell me how to reference them?
Here are my models:
class Clown(models.Model):
name = models.CharField(max_length=255)
def edit_link(self):
return ...
class Circus(models.Model):
clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
name = models.CharField(max_length=255)
class WorkedAt(models.Model):
clown = models.ForeignKey(Clown)
circus = models.ForeignKey(Circus)
and my admin:
class ClownInline(admin.TabularInline):
model = WorkedAt
fields = ['clown__name','clown__edit_link']
class CircusAdmin(admin.ModelAdmin):
inlines = [
ClownInline,
]
exclude = ('clowns',)
However I get this error:
Unknown field(s) (clown__name) specified for WorkedAt
(I'm on Django 1.6)
Update:
Why won't this work either. (Added calculated field to through model.)
class Clown(models.Model):
name = models.CharField(max_length=255)
def edit_link(self):
return ...
class Circus(models.Model):
clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
name = models.CharField(max_length=255)
class WorkedAt(models.Model):
clown = models.ForeignKey(Clown)
circus = models.ForeignKey(Circus)
#property
def edit_link(self):
return self.clown.edit_link()
and my admin:
class ClownInline(admin.TabularInline):
model = WorkedAt
fields = ['edit_link']
class CircusAdmin(admin.ModelAdmin):
inlines = [
ClownInline,
]
exclude = ('clowns',)
Try this. Hope it solves your problem
class ClownInline(admin.TabularInline):
model = WorkedAt
fields = ['clown_name', 'clown_edit_link']
readonly_fields = ['clown_name', 'clown_edit_link']
def clown_name(self, instance):
return instance.clown.name
clown_name.short_description = 'clow name'
def clown_edit_link(self, instance):
url = reverse("admin:%s_%s_change" % (instance.clown._meta.app_label, instance.clown._meta.module_name), args=(instance.clown.pk,))
return '%s' % (url, instance.clown.name)
clown_edit_link.allow_tags = True
class CircusAdmin(admin.ModelAdmin):
inlines = [
ClownInline,
]
exclude = ('clowns',)
I don't know if anyone still needs this, because this question is 4 years old but this solved my problem for in Django 2.0.3:
# models.py
class Clown(models.Model):
name = models.CharField(max_length=255)
def edit_link(self):
return ...
class Circus(models.Model):
clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
name = models.CharField(max_length=255)
class WorkedAt(models.Model):
clown = models.ForeignKey(Clown)
circus = models.ForeignKey(Circus)
# admin.py
class WorkedAtInline(admin.TabularInline):
model = WorkedAt
extra = 1
class WorkedAtAdmin(admin.ModelAdmin):
inlines = (WorkedAtInline,)
admin.site.register(Clown, WorkedAtAdmin)
Hope this helps anyone that stumbles upon this problem and looks into this answer.