Django-formset custom queryset

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})"
Вернуться на верх