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})"