Issue
I have a model `Transaction' and ModelForm to create one :
class Transaction(models.Model):
""" Invoice model.
Represents a basic income/outcome transaction. """
title = models.CharField(max_length=32, verbose_name="Title")
category = models.ForeignKey(Category, related_name="transactions", on_delete=models.CASCADE, null=True, blank=True)
operation = models.CharField(max_length=8, choices=OPERATION_TYPE, verbose_name="operation")
value = models.DecimalField(max_digits=14, decimal_places=2, verbose_name="value")
currency = models.CharField(max_length=3, choices=CURRENCY_CHOICE, verbose_name="currency")
comment = models.CharField(max_length=255, null=True, blank=True)
date_created = models.DateField(auto_now_add=True, blank=True, null=True)
class Meta:
verbose_name_plural = "Transactions"
ordering = ["-date_created"]
class NewInvoiceForm(forms.ModelForm):
category = TreeNodeChoiceField(queryset=Category.objects.all())
class Meta:
model = Transaction
fields = ("title", "category", "operation", "value", "currency")
help_texts = {
"operation": _("Money spent/received. For expenses use a negative value.")
}
I have a Preference model linked with each user to store settings :
class Config(models.Model):
""" Represents user's preferences. """
user = models.OneToOneField(CustomUser, related_name="config", on_delete=models.CASCADE)
currency = models.CharField(max_length=3, choices=CURRENCY_CHOICE, default=DEFAULT_SETTINGS["currency"])
language = models.CharField(max_length=56, choices=LANGUAGE_CHOICE, default=DEFAULT_SETTINGS["language"])
class Meta:
verbose_name = "config"
verbose_name_plural = "configs"
I'm trying to get user's currency from Config
model as initial value for Transaction
creation form. But initial value never renders.
My view :
def create_transaction_view(request):
if request.method == "POST":
form = NewInvoiceForm(
request.POST,
instance=request.user
)
if form.is_valid():
new_invoice = Transaction(**form.cleaned_data)
# retrieving user's currency preference for further converting if income is different from base currency
user_currency = request.user.config.currency
# performing currency conversion to maintain consistent data for statistic and analyse
if user_currency != new_invoice.currency:
transaction_converted_value = CurrencyExchangeManager.currency_converter(
value=new_invoice.value,
exchange_to=user_currency,
base=new_invoice.currency
)
new_invoice.value = transaction_converted_value
new_invoice.currency = user_currency
new_invoice.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER', "/"))
I always get a 'dash' field as initial choice. Appreciate any suggestions on this topics.
Solution
Your code is mostly correct, but you need to check if it's handling both GET
and POST
requests appropriately for your form.
Here request.method == "POST"
condition is crucial for processing form submissions, where you handle the data sent by the user. This block is where the form's data is validated and processed.
But when the user submits the form, this block takes charge, processing the submitted data, validating it, and then performing necessary operations like saving the data or doing additional processing, such as currency conversion in your case. Till this point your code was correct.
But for initial form rendering, particularly for GET
requests, the form should be set up with initial values which is missing from your code.
When the form is first requested by the user, it's typically a GET
request. In this scenario, you should provide initial values for the form fields. In your application, this means setting the initial value of the currency field to the user's preferred currency. You can do this by using the the else
block of your view function, which handles the GET request like this:
else:
user_currency = request.user.config.currency
form = NewInvoiceForm(initial={'currency': user_currency})
The form is instantiated with the initial value for the currency, ensuring that when the user accesses the form to create a new transaction, they see their preferred currency pre-selected.
Here is the full update code that you need in views.py
for create_transaction_view
method
def create_transaction_view(request):
if request.method == "POST":
form = NewInvoiceForm(
request.POST,
instance=request.user
)
if form.is_valid():
new_invoice = Transaction(**form.cleaned_data)
# retrieving user's currency preference for further converting if income is different from base currency
user_currency = request.user.config.currency
# performing currency conversion to maintain consistent data for statistic and analyse
if user_currency != new_invoice.currency:
transaction_converted_value = CurrencyExchangeManager.currency_converter(
value=new_invoice.value,
exchange_to=user_currency,
base=new_invoice.currency
)
new_invoice.value = transaction_converted_value
new_invoice.currency = user_currency
new_invoice.save()
else:
user_currency = request.user.config.currency
form = NewInvoiceForm(initial={'currency': user_currency})
return HttpResponseRedirect(request.META.get('HTTP_REFERER', "/"))
Note: You can even optimize the code a little by initializing this user_currency = request.user.config.currency
at the beginning of the create_transaction_view
function so we don't need to repeat this twice in the code. I gave it like that for your understanding.
Answered By - Mohammad Golam Dostogir
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.