Django Admin, how to update select user field with my own queryset after adding new foreign object

350 views
Skip to first unread message

Héctor Alonso Lozada Echezuría

unread,
Jan 8, 2021, 1:59:46 PM1/8/21
to django...@googlegroups.com
Best regards

I have a very simple warehouse model that is related to the contrib.auth.User model through the asigned_seller field
which should only allow those users with the seller role

class PersonalWarehouse(ProductsMixin, WarehouseBase):
    channel = models.ForeignKey(
        SalesChannel,
        verbose_name=_('Sales channel'),
        on_delete=models.PROTECT
    )
    asigned_seller = models.ForeignKey(
        User,
        verbose_name=_('Asigned seller'),
        blank=True,
        null=True,
        on_delete=models.SET_NULL
    )
    is_close = models.BooleanField(
        verbose_name=_('Is it close?'),
        default=False
    )
    created_at = models.DateTimeField(
        verbose_name=_('Created at'),
        auto_now_add=True
    )
    deadline = models.DateField(
        verbose_name=_('Deadline'),
        default=date(now.year + now.month // 12, now.month % 12 + 1, 1) - timedelta(1)
    )

    class Meta:
        verbose_name = _('Personal warehouse')
        verbose_name_plural = _('Personal warehouses')
        permissions = [
            ('close_personal_warehouses', 'Can close warehouse')
        ]

    def __str__(self):
        return self.name

    def __repr__(self):
        return f'<PersonalWarehouse: {self.name}>'

In my admin I have.

@admin.register(PersonalWarehouse)
class PersonalWarehouseAdmin(admin.ModelAdmin):
    change_form_template = 'change_form.html'

    exclude = ('is_close', )
    list_display = ('name', 'asigned_seller', 'is_close', 'deadline', )
    list_filter = ('asigned_seller', 'is_close', 'created_at', 'deadline', )
    ordering = ['-deadline']
    search_fields = ['name']
    actions = [close_personal_warehouses]

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'asigned_seller':
            kwargs['queryset'] = User.objects.filter(groups__name='Seller')
            field = super().formfield_for_foreignkey(
                db_field, request, **kwargs)
            field.label_from_instance = self.get_user_label
            return field

        return super().formfield_for_foreignkey(db_field, request, **kwargs)

    def get_user_label(self, user):
        return user.get_full_name()

the problem exists when I add a new user from the warehouse template, it is added without any role and therefore appears listed

imagen.png
imagen.png

imagen.png

after refreshing the page I get only those users with the seller role

imagen.png

So how can I refresh the select widget so that only the users with the seller role appear after the ajax event?

--
Héctor Alonso Lozada Echezuría

Libre de virus. www.avast.com

Mike Dewhirst

unread,
Jan 9, 2021, 12:54:31 AM1/9/21
to django...@googlegroups.com
On 9/01/2021 5:58 am, Héctor Alonso Lozada Echezuría wrote:
> Best regards
>
> I have a very simple warehouse model that is related to the
> contrib.auth.User model through the asigned_seller field
> which should only allow those users with the seller role
>
> class PersonalWarehouse(ProductsMixin, WarehouseBase):
> channel= models.ForeignKey(
> SalesChannel,
> verbose_name=_('Sales channel'),
> on_delete=models.PROTECT
> )
> asigned_seller= models.ForeignKey(
> User,
> verbose_name=_('Asigned seller'),
> blank=True,
> null=True,
> on_delete=models.SET_NULL
> )
> is_close= models.BooleanField(
> verbose_name=_('Is it close?'),
> default=False
> )
> created_at= models.DateTimeField(
> verbose_name=_('Created at'),
> auto_now_add=True
> )
> deadline= models.DateField(
> verbose_name=_('Deadline'),
> default=date(now.year+ now.month// 12, now.month% 12 + 1, 1) - timedelta(1)
> )
>
> class Meta:
> verbose_name= _('Personal warehouse')
> verbose_name_plural= _('Personal warehouses')
> permissions= [
> ('close_personal_warehouses', 'Can close warehouse')
> ]
>
> def __str__(self):
> return self.name
>
> def __repr__(self):
> return f'<PersonalWarehouse: {self.name <http://self.name>}>'
>
> In my admin I have.
>
> @admin.register(PersonalWarehouse)
> class PersonalWarehouseAdmin(admin.ModelAdmin):
> change_form_template= 'change_form.html'
>
> exclude= ('is_close', )
> list_display= ('name', 'asigned_seller', 'is_close', 'deadline', )
> list_filter= ('asigned_seller', 'is_close', 'created_at', 'deadline', )
> ordering= ['-deadline']
> search_fields= ['name']
> actions= [close_personal_warehouses]
>
> def formfield_for_foreignkey(self, db_field, request, **kwargs):
> if db_field.name== 'asigned_seller':
> kwargs['queryset'] = User.objects.filter(groups__name='Seller')
> field= super().formfield_for_foreignkey(
> db_field, request, **kwargs)
> field.label_from_instance= self.get_user_label
> return field
>
> return super().formfield_for_foreignkey(db_field, request, **kwargs)
>
> def get_user_label(self, user):
> return user.get_full_name()
>
> the problem exists when I add a new user from the warehouse template,
> it is added without any role and therefore appears listed

Perhaps you need to filter the queryset itself. Here is an example of
one of mine ...

def get_queryset(self, request):
""" Limit the chemicals visible to just those owned by the company
of which the user is an employee.
"""
company = get_user_company(request.user)
qs = super().get_queryset(request)
return qs.filter(chemical__company=company)



If you have a custom user, you can put the user into the correct
group(s) on creation using

https://docs.djangoproject.com/en/2.2/ref/signals/#django.db.models.signals.post_save

Otherwise, in formfield_for_foreignkey() you can insert a line which
tests request.user for membership of "Seller" and if not, put the user
into that group before checking if db_field.name == 'assigned_seller'


>
> imagen.png
> imagen.png
>
> imagen.png
>
> after refreshing the page I get only those users with the seller role
>
> imagen.png
>
> So how can I refresh the select widget so that only the users with the
> seller role appear after the ajax event?
>
> --
> Héctor Alonso Lozada Echezuría
>
> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
> Libre de virus. www.avast.com
> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com
> <mailto:django-users...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/CADTS2YysaQxyz643ZneQ-D2gbe0B%2BKDHJe7VkGLW_MiPiq3awQ%40mail.gmail.com
> <https://groups.google.com/d/msgid/django-users/CADTS2YysaQxyz643ZneQ-D2gbe0B%2BKDHJe7VkGLW_MiPiq3awQ%40mail.gmail.com?utm_medium=email&utm_source=footer>.


--
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Just
ask and I'll send it to you. Your email software can handle signing.


OpenPGP_signature
Reply all
Reply to author
Forward
0 new messages