In a view that creates a new object, successful creation should redirect to a different page for edit. Instead, redirect remains on the new object page with the data just used. Stepping through the code in Visual Studio code, the expression HttpResponseRedirect(reverse('meal:mealEdit', args=(id, )))
evaluates to .../meal/{id}/edit
yet renders .../meal/new
. Guess the browser just likes that page?
Some code:
view.py
:
def mealNew(request):
if request.method=='POST':
form = MealForm(request.POST)
if form.is_valid():
m_meal = form.save()
id = m_meal.id
HttpResponseRedirect(reverse('meal:mealEdit', args=(id, )))
else:
form = MealForm()
return render(request, 'meal/new_meal_form.html', {
'title' : 'New Meal',
'form' : form,
})
model.py
:
class Meal(models.Model):
meal_type = models.CharField(
choices=MEAL_CHOICES,
max_length=9,
default = None,
)
meal_date = models.DateField()
foods = models.ManyToManyField(Food)
def __str__(self):
if self.meal_type == '1':
return 'Dinner'
elif self.meal_type == '2':
return 'Dinner'
else:
return 'Breakfast'
def get_absolute_url(self):
return reverse('mealEdit', kwargs={'pk': self.pk})
class Meta:
db_table = "meal"
ordering = ['-meal_date', 'meal_type']
verbose_name = 'Meal type'
class MealForm(ModelForm):
class Meta:
model = Meal
fields = ['meal_type', 'meal_date']
widgets = {
'meal_type' : forms.RadioSelect(),
'meal_date' : DatePickerInput}
def clean_meal_date(self):
beginning = Meal.objects.order_by('id')[0].meal_date
data = self.cleaned_data['meal_date']
if data < beginning:
raise ValidationError("Date is earlier than earliest meal")
return data
def clean(self):
cleaned_data = super().clean()
m_date = cleaned_data.get('meal_date')
m_type = cleaned_data.get('meal_type')
if Meal.objects.filter(meal_type=m_type, meal_date=m_date ):
raise ValidationError("Meal already exists for this date")
new_meal_form.html
:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block body %}
<h1>Create new Meal</h1>
<div class="row">
<div class="col-6">
<form action="{% url 'meal:mealNew' %}" method="POST">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Save">
</form>
<div id='food'></div>
</div>
</div>
<a href="{# path('app_meal_index') #}">back to list</a>
{% endblock %}
edit.html
:
{# meal/templates/meal/edit.html #}
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{# requires included, tableName, available #}
{% block body %}
<div class='row'>
<div class='col-3'>
<form action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Save">
</form>
</div>
<div class='col-4'>
<table class='table' id='ready_foods'>
<thead>
<tr>
<th>Included in meal</th>
</tr>
</thead>
<tbody>
{% for food in included %}
<tr>
<td data-foodid={{ food.id }} >{{ food }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class='col-4'>
{% include 'food/_foods.html' %}
</div>
</div>
{% endblock %}