I am creating app for control transaction (expense, income, budget). I want each user to be able to create their own spending categories and their own expenses. All expenses and categories created by a user are to be visible only to that user.
If user A creates the category "Food123" then user B cannot see it. He can create his own such category.
I've created two models - Category and Expense.
class Category(models.Model):
name = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="category")
class Expense(models.Model):
name = models.CharField(max_length=100)
amount = models.DecimalField(max_digits=8, decimal_places=2)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="expense")
I use a generic view when creating expenses and categories.
class ExpenseListView(LoginRequiredMixin, ListView):
model = Expense
context_object_name = 'expense'
template_name = 'expense/expense_list.html'
def get_queryset(self):
return self.request.user.expense.all()
class ExpenseCreateView(CreateView):
model = Expense
success_url = '/record/expense'
form_class = ExpenseForm
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return HttpResponseRedirect(self.get_success_url())
class CategoryCreateView(CreateView):
model = Category
success_url = '/record/expense'
form_class = CategoryForm
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return HttpResponseRedirect(self.get_success_url())
What is more, I've used forms.py.
class ExpenseForm(forms.ModelForm):
class Meta:
model = Expense
fields = ('name', 'amount', 'category')
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ('name',)
Unfortunetly, when user A create category "IT" it automatically goes to user B. When user B creates his expense he also sees this "IT" category that A created, not B.
How can I limit the display of categories in the form to only those created by a particular user?
The problem is because you're not filtering the model fields by your user in the ExpenseForm
(like you are doing in the ExpenseListView.get_queryset
).
To do it, you will need to change a bit your logic. you can try something like this:
# forms.py
class ExpenseForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
# limit the category field queryset
self.fields['category'] = forms.ModelChoiceField(
queryset=user.category.all())
)
class Meta:
model = Expense
fields = ('name', 'amount', 'category')
# views.py
class ExpenseCreateView(CreateView):
...
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
# inject the user in the form instantiation
kwargs['user'] = self.request.user
return kwargs