Django admin: list not correct (duplicate rows) - django

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

Related

django rest_framework how to display nested relationship

I'm trying to display foreign related fields like this example and it works
{
"reqid": 10,
"reqdate": "2022-12-05",
"reqdescription": "Aircon Not working",
"officerequestor": "OVCAA ",
"officeid": "PPD ",
"inspection": {
"insdate": "2022-12-06",
"diagnosis": "need to buy prism",
"inspector": "EMP-322 "
}
},
this is my serializers.py
class RequestAdditionDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = Inspection
fields = ['insdate',
'diagnosis',
'inspector'
]
class RequestorSerializer(serializers.ModelSerializer):
inspection = RequestAdditionDetailsSerializer(read_only=True)
class Meta:
model = Request
fields = ['reqid',
'reqdate',
'reqdescription',
'officerequestor',
'officeid',
'inspection'
]
My question is can I do this the other way around like this
{
"inspectid": 5,
"reqid": "10",
"insdate": "2022-12-06",
"diagnosis": "need to buy prism",
"inspector": "EMP-322",
"isinspected": {
"reqdescription": "Aircon Not working",
"reqdate": "2022-12-05",
"officerequestor": "OVCAA"
}
},
this is what I've tried, tbh I don't think this will work is there a solution for this.
if no maybe i'll add additional columns on inspection like reqdescription,reqdate etc.. just to show them
class InspectionAdditionalDetailsViewSerializer(serializers.ModelSerializer):
class Meta:
model = Request
fields = ['reqdescription',
'reqdate',
'officerequestor'
]
class InspectionSerializer(serializers.ModelSerializer):
request_details = InspectionAdditionalDetailsViewSerializer(read_only=True)
class Meta:
model = Inspection
fields = ['inspectid',
'reqid',
'insdate',
'diagnosis',
'inspector',
'isinspected',
'request_details'
]
this is my models.py
class Inspection(models.Model):
inspectid = models.AutoField(primary_key=True)
reqid = models.OneToOneField('Request', models.DO_NOTHING, db_column='reqid', blank=True, null=True)
class Meta:
managed = False
db_table = 'inspection'
class Request(models.Model):
reqid = models.AutoField(primary_key=True)
class Meta:
managed = False
db_table = 'request'
You have defined the OneToOne field name reqid therefore you should use it as serializer key.
Noted that Django will add _id to the field so it will become reqid_id in your database, it's best to name it req or request only to refer to related object.
class InspectionAdditionalDetailsViewSerializer(serializers.ModelSerializer):
class Meta:
model = Request
fields = [
'reqdescription',
'reqdate',
'officerequestor',
]
class InspectionSerializer(serializers.ModelSerializer):
reqid = InspectionAdditionalDetailsViewSerializer(read_only=True)
class Meta:
model = Inspection
fields = [
'inspectid',
'reqid',
'insdate',
'diagnosis',
'inspector',
'isinspected',
]

Addition of css class on widget file input has no effect

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

Trying to make a django rest api that doesn't look like my models

I'm trying to make an API for an outside group where I define user access. I have a setup in django that makes it easy to administer, but I would like the output to be quite simplistic for the other team.
This is the output I'm looking for would be something like:
{
"user_list": {
"user": {
"username": "username1",
"top_accesses": ["top_access_1", "top_access_2", "top_access_5"],
"middle_accesses": ["middle_access_1", "middle_access_2", "middle_access_7"],
"lower_accesses": ["lower_access_1", "lower_access_2", "lower_access_22"],
},
"user": {
"username": "username2",
"top_accesses": ["top_access_1", "top_access_2", "top_access_8"],
"middle_accesses": ["middle_access_3", "middle_access_5", "middle_access_6"],
"lower_accesses": ["lower_access_21", "lower_access_33", "lower_access_36"],
}
}
}
However, I'm having trouble using django's built in ORM to come up with these sets from my models. I can think of how to do it in SQL, but this isn't a particularly clean method. I know there must be a better way to do it since using TabularInline shows exactly what I want to see in the admin page
Here are my models:
class TopAccess(models.Model):
name = models.CharField(max_length=100)
site_user_access = models.ManyToManyField(User, blank=True)
site_group_access = models.ManyToManyField(Group, blank=True)
class Meta:
verbose_name_plural = "Top Access"
def __str__(self):
return self.name
class MiddleAccess(models.Model):
name = models.CharField(max_length=100)
site_user_access = models.ManyToManyField(User, blank=True)
site_group_access = models.ManyToManyField(Group, blank=True)
class Meta:
verbose_name_plural = "Middle Access"
def __str__(self):
return self.name
class LowerAccess(models.Model):
name = models.CharField(max_length=100)
site_user_access = models.ManyToManyField(User, blank=True)
site_group_access = models.ManyToManyField(Group, blank=True)
class Meta:
verbose_name_plural = "Lower Access"
def __str__(self):
return self.name
Ideally I would be able to return a query object that plays well with the django-rest-framework in the end, since I like how nicely it returns the same data in whichever form is requested
Edit:
This is what I'm thinking is going to be close to the solution, but I know I'm using class inheritance incorrectly
class MaybeThisCouldWork(User):
t_user = TopAccess.objects.filter(site_user_access=User)
m_user = MiddleAccess.objects.filter(site_user_access=User)
l_user = LowerAccess.objects.filter(site_user_access=User)
user_groups = User.objects.filter(id=User)
for user_group in user_groups:
t_group = TopAccess.objects.filter(
site_group_access=user_groups
)
m_group = MiddleAccess.objects.filter(
site_group_access=user_groups
)
l_group = LowerAccess.objects.filter(
site_group_access=user_groups
)
t_user = t_user | t_group
m_user = m_user | m_group
l_user = l_user | l_group
You could use serializers, may be something like this,
class TopAccessSerializer(serializers.ModelSerializer):
class Meta:
model = TopAccess
fields = ['name']
class MiddleAccessSerializer(serializers.ModelSerializer):
class Meta:
model = MiddleAccess
fields = ['name']
class LowerAccessSerializer(serializers.ModelSerializer):
class Meta:
model = LowerAccess
fields = ['name']
class UserSerializer(serializers.ModelSerializer):
topaccess = TopAccessSerializer(source='topaccess_set', many=True)
middleaccess = MiddleAccessSerializer(source='middleaccess_set', many=True)
loweraccess = LowerAccessSerializer(source='loweraccess_set', many=True)
class Meta:
model = User
fields = ['username', 'topaccess', 'middleaccess', 'loweraccess']

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 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.