Автоматическая отправка формы django без создания бесконечного цикла
У меня есть проблема в моем приложении, которую я не могу решить наилучшим способом. Я изучаю Django и практически не имею опыта работы с Javascript, поэтому любая помощь будет оценена по достоинству. Возможно, это недостаток дизайна, поэтому я открыт для других идей.
Проблема Когда пользователь впервые попадает на страницу своей приборной панели, ему необходимо выбрать курс валюты на форме, в которой он хочет просматривать свои данные, например, USD, AUD, GBP и т.д. После того, как они отправят свой курс валюты, их приборная панель станет активной и доступной для просмотра. Я бы хотел, чтобы этот выбор оставался представленным при обновлении/загрузке или автоматически отправлялся при обновлении/загрузке. Таким образом, эта валюта останется, если пользователь не введет другую валюту.
Смотрите изображения до/после для контекста (игнорируйте значения, так как они неточны):
Attempted solution I have tried using Javascript to auto submit on load which causes and infinite loop. I have read to use action to redirect to another page but i need it to stay on the same page. Unless this can be configured to only submit once after refresh/load I don't think this will work
<script type="text/javascript">
$(document).ready(function() {
window.document.forms['currency_choice'].submit();
});
</script>
<div class="container">
<div>
<span>
<h1>My Dashboard</h1>
</span>
<span>
<form method="post" name="currency_choice">
{% csrf_token %}
{{ form_c.as_p }}
<button class="btn btn-outline-success btn-sm">Submit</button>
</form>
</span>
</div>
</div>
ФОРМА
class CurrencyForm(forms.ModelForm):
currency = forms.ChoiceField(choices=currencies, label='Choose Currency:',)
class Meta:
model = UserCurrency
fields = (
'currency',
)
МОДЕЛЬ
class UserCurrency(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
currency = models.CharField(max_length=10)
Вид
class MyDashboardView(TemplateView):
template_name = 'coinprices/my-dashboard.html'
def get(self, request, **kwargs):
form_c = CurrencyForm(prefix='form_c')
return render(request, self.template_name, {
'form_c': form_c,
})
def post(self, request):
currency = None
form_c = CurrencyForm(request.POST, prefix='form_c')
if request.method == 'POST':
if form_c.is_valid():
cur = UserCurrency.objects.filter(user_id=request.user.id)
cur.delete()
post = form_c.save(commit=False)
post.user = request.user # Registers the entry by the current user
post.save()
currency = UserCurrency.objects.filter(user_id=request.user.id).values('currency')
currency = currency[0]['currency']
else:
form_c = CurrencyForm()
rates = {'USD': 1.0, 'AUD': 1.321, 'GBP': 0.764, 'CAD': 1.249}
deposit = 10000 / rates[currency]
context = {
'currency': currency,
'deposit': dep,
'form_c': form_c,
}
return render(request, 'coinprices/my-dashboard.html', context)
сделайте новый временный шаблон только с этим содержимым, сделайте представление для рендеринга и добавьте вызов представления в urls.py
{% csrf_token %}
{{ form_c.as_p }}
обновите текущий шаблон и вставьте ajax (я предполагаю, что вы имеете представление о jquery ajax)
<form method="post" name="currency_choice">
<div id="currency-choice">
{% csrf_token %}
{{ form_c.as_p }}
</div>
<button class="btn btn-outline-success btn-sm">Submit</button>
</form>
<script>
$.ajax({
url : '{% url 'url-of-new-template' %}',
success : function(response){
$('#currency-choice').html(response)
},
});
</script>
Обычной практикой для такого типа ситуаций является расчет и отображение информации о депозите в методе представления get. Если форма отправлена, метод post проверяет и сохраняет отправку, а затем автоматически перезагружает страницу.
Javascript не требуется, поэтому вы можете удалить его из вашего шаблона.
Я модифицировал вашу модель UserCurrency, чтобы использовать отношения OneToOneField с User. Это означает, что на каждую запись User может приходиться не более одной такой записи. Это также означает, что вы можете получить доступ к сохраненной валюте непосредственно из экземпляра пользователя.
Я также установил валюту по умолчанию "USD".
В представлении блоки try/except создают временный экземпляр UserCurrency, если он еще не существует.
МОДЕЛЬ
class UserCurrency(models.Model):
user = models.OneToOneField(
User,
primary_key=True,
related_name="user_currency",
on_delete=models.CASCADE)
currency = models.CharField(max_length=10, default="USD")
VIEW
from django.http import HttpResponseRedirect
class MyDashboardView(TemplateView):
template_name = 'coinprices/my-dashboard.html'
def get(self, request, **kwargs):
"""
Get the saved currency, calculate the deposit, and display.
"""
try:
user_currency = request.user.user_currency
except UserCurrency.DoesNotExist:
user_currency = UserCurrency(user=request.user)
rates = {'USD': 1.0, 'AUD': 1.321, 'GBP': 0.764, 'CAD': 1.249}
deposit = 10000 / rates[user_currency.currency]
form_c = CurrencyForm(instance=user_currency, prefix='form_c')
return render(request, self.template_name, {
'currency': user_currency.currency,
'deposit': deposit,
'form_c': form_c,
})
def post(self, request):
"""
Validate the posted data, save/update the model instance,
and reload the page.
"""
try:
user_currency = request.user.user_currency
except UserCurrency.DoesNotExist:
user_currency = UserCurrency(user=request.user)
form_c = CurrencyForm(request.POST, instance=user_currency, prefix='form_c')
if form_c.is_valid():
post.save()
return HttpResponseRedirect(request.path_info)
