[Python] django-formset custom queryset

Discussão em 'Python' iniciado por Stack, Abril 28, 2025.

  1. Stack

    Stack Membro Participativo

    I am using the https://django-formset.fly.dev/ library, version 1.7.6. I'm trying to set a custom queryset on a ModelChoiceField, but I'm having trouble filtering the queryset based on the request object. Specifically, I want to filter and set the queryset to include only certain InRGPItem objects.

    Could you advise on how to properly set a custom queryset for ModelChoiceField in this context?

    forms.py

    # django libraries
    from django.forms.widgets import HiddenInput
    from django.forms.models import ModelChoiceField, ModelForm

    # django-formset libraries
    from formset.collection import FormCollection
    from formset.widgets import Selectize, DateInput, TextInput, Button
    from formset.renderers.bootstrap import FormRenderer as BootstrapFormRenderer

    # project models
    from rgp_entry_app.models import OutRGPEntry, OutRGPItem, InRGPItem


    class OutRGPItemForm(ModelForm):

    in_rgp_item = ModelChoiceField(
    label="In RGP Item",
    queryset=InRGPItem.objects.none(), # Using direct empty queryset instead
    empty_label="Select",
    # to_field_name="guid",
    # widget=Selectize(
    # search_lookup="name__icontains",
    # ),
    )
    class Meta:
    model = OutRGPItem
    fields = ['in_rgp_item', 'sent_qty', 'note']
    widgets = {
    'note': Textarea(attrs={'rows': 1}),
    }

    class OutRGPItemCollection(FormCollection):
    outrgpitem = OutRGPItemForm() # ✅ repeatable formset items
    related_field = 'out_rgp_entry'
    legend = "Out RGP Items"
    min_siblings = 1
    is_sortable = True
    ignore_marked_for_removal = True

    class OutRGPEntryCollection(FormCollection):
    outrgpentry = OutRGPEntryForm()
    outrgpitem_set = OutRGPItemCollection()
    legend = "Out RGP Entry"
    default_renderer = BootstrapFormRenderer(
    form_css_classes='row',
    field_css_classes={
    # '*': 'mb-2 col-4',
    'chalan_no': 'col-sm-4',
    'chalan_date': 'col-sm-4',
    'rgp_date': 'col-sm-4',
    'in_rgp_item': 'mb-2 col-sm-4',
    'sent_qty': 'mb-2 col-sm-4',
    'note': 'mb-2 col-sm-4',
    },
    )


    views.py

    # django libraries import
    from django.shortcuts import render, redirect, get_object_or_404
    from django.http import HttpRequest, HttpResponseRedirect, JsonResponse, HttpResponse, HttpResponseBadRequest

    # third-party libraries
    from formset.views import FormCollectionView, FormView, EditCollectionView, FormViewMixin

    # project forms import
    from rgp_entry_app.forms import OutRGPEntryCollection

    # project models import
    from rgp_entry_app.models import RGPCustomer, InRGPEntry, InRGPItem


    class OutRGPEntryCreateView(EditCollectionView):
    pk_url_kwarg = 'in_rgp_entry_guid'
    model = InRGPEntry
    collection_class = OutRGPEntryCollection
    template_name = 'admin_panel/rgp_entry/out_rgp_entry/out_entry_form.html'
    success_url = reverse_lazy("rgp_entry_app:rgp_entry_view")

    def get_object(self, queryset=None):
    if queryset is None:
    queryset = self.get_queryset()
    guid = self.kwargs.get(self.pk_url_kwarg)
    if guid is not None:
    queryset = queryset.filter(guid=guid)
    obj = get_object_or_404(queryset)
    return obj

    def get_initial(self):
    print(f"START:get_initial")
    initial = super().get_initial()
    print(f"BEFORE:initial: {initial}")
    in_rgp_entry = self.get_object()
    print(f"in_rgp_entry: {in_rgp_entry}")

    # Set initial values for the main form
    initial['outrgpentry'] = {
    'in_rgp_entry': in_rgp_entry.id,
    }

    # Set initial values for the items collection
    initial['outrgpitem_set'] = []
    for item in in_rgp_entry.inrgpitem_set.all():
    initial['outrgpitem_set'].append({
    'outrgpitem' : {
    'in_rgp_item': item.id, # Use item.id instead of item object
    'sent_qty': item.qty, # Set initial sent_qty to the original qty
    }
    })

    print(f"AFTER:initial: {initial}")
    print(f"END:get_initial")
    return initial

    def get_context_data(self, **kwargs):
    print(f"START:get_context_data")
    context = super().get_context_data(**kwargs)
    context["rgp_entry_nav"] = "active"
    context["in_rgp_entry"] = self.get_object() # Add InRGPEntry object to context
    print(f"END:get_context_data")
    return context


    models.py

    # django libraires
    from django.db import models
    from django.utils import timezone

    # project model
    from auth_app.models import CreatedAtAndUpdatedAt

    # third party libraries
    import uuid

    # Create your models here.
    class ActiveCustomerManager(models.Manager):
    def get_queryset(self):
    """Retrieve all active users"""
    return super().get_queryset().filter(is_active=True)

    class InActiveCustomerManager(models.Manager):
    def get_queryset(self):
    """Retrieve all inactive users"""
    return super().get_queryset().filter(is_active=False)

    class RGPCustomer(CreatedAtAndUpdatedAt):
    guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    name = models.CharField(max_length=255, unique=True)
    created_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="rgp_customer_created_by")
    updated_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="rgp_customer_updated_by")
    is_active = models.BooleanField("active", default=True)
    deleted_at = models.DateTimeField(null=True, blank=True) # Store delete timestamp

    objects = models.Manager()
    active_customers = ActiveCustomerManager()
    in_active_customers = InActiveCustomerManager()

    class Meta:
    ordering = ['-id']

    def __str__(self):
    return self.name

    def delete(self, *args, **kwargs):
    """Soft delete method using is_active field."""
    self.is_active = False
    self.deleted_at = timezone.now()
    self.save(update_fields=["is_active", "deleted_at"])

    def restore(self):
    """Restore a soft-deleted user."""
    self.is_active = True
    self.deleted_at = None
    self.save(update_fields=["is_active", "deleted_at"])


    class ActiveRGPItemManager(models.Manager):
    def get_queryset(self):
    """Retrieve all active users"""
    return super().get_queryset().filter(is_active=True)

    class InActiveRGPItemManager(models.Manager):
    def get_queryset(self):
    """Retrieve all inactive users"""
    return super().get_queryset().filter(is_active=False)

    class RGPItem(CreatedAtAndUpdatedAt):
    guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    name = models.CharField(max_length=255, unique=True)
    is_active = models.BooleanField("active", default=True,)
    created_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="rgp_item_created_by")
    updated_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="rgp_item_updated_by")
    deleted_at = models.DateTimeField(null=True, blank=True) # Store delete timestamp

    objects = models.Manager()
    active_rgp_items = ActiveRGPItemManager()
    in_active_rgp_items = InActiveRGPItemManager()

    def __str__(self):
    return self.name

    def delete(self, *args, **kwargs):
    """Soft delete method using is_active field."""
    self.is_active = False
    self.deleted_at = timezone.now()
    self.save(update_fields=["is_active", "deleted_at"])

    def restore(self):
    """Restore a soft-deleted user."""
    self.is_active = True
    self.deleted_at = None
    self.save(update_fields=["is_active", "deleted_at"])

    class InRGPEntry(CreatedAtAndUpdatedAt):
    guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    rgp_customer = models.ForeignKey(RGPCustomer, on_delete=models.CASCADE)
    rgp_no = models.CharField(max_length=50, unique=True)
    rgp_date = models.DateField()
    created_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="in_rgp_entry_created_by")
    updated_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="in_rgp_entry_updated_by")

    def __str__(self):
    return f"{self.rgp_no} - {self.rgp_customer.name}"


    class InRGPItem(CreatedAtAndUpdatedAt):
    guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    in_rgp_entry = models.ForeignKey(InRGPEntry, on_delete=models.CASCADE)
    rgp_item = models.ForeignKey(RGPItem, on_delete=models.CASCADE)
    serial_no = models.PositiveSmallIntegerField()
    qty = models.PositiveSmallIntegerField()

    def __str__(self):
    return f"{self.serial_no} - {self.rgp_item.name} (Qty: {self.qty})"


    class OutRGPEntry(CreatedAtAndUpdatedAt):
    guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    in_rgp_entry = models.ForeignKey(InRGPEntry, on_delete=models.CASCADE)
    chalan_no = models.CharField(max_length=50, unique=True)
    chalan_date = models.DateField()
    created_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="out_rgp_entry_created_by")
    updated_by = models.ForeignKey('auth_app.User', on_delete=models.PROTECT, null=True, blank=False, related_name="out_rgp_entry_updated_by")

    def __str__(self):
    return f"{self.chalan_no} - {self.in_rgp_entry.rgp_no}"


    class OutRGPItem(CreatedAtAndUpdatedAt):
    guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    out_rgp_entry = models.ForeignKey(OutRGPEntry, on_delete=models.CASCADE)
    in_rgp_item = models.ForeignKey(InRGPItem, on_delete=models.CASCADE)
    sent_qty = models.PositiveSmallIntegerField()
    note = models.TextField(blank=True, null=True)

    def __str__(self):
    return f"{self.in_rgp_item.serial_no} - {self.in_rgp_item.rgp_item.name} (Sent: {self.sent_qty})"

    Continue reading...

Compartilhe esta Página