Django form for many-to-many model. How do I fill a form from views/template?
django, django-forms, django-orm, django-templates
Solution
I managed to make it work.
For anyone in the future by accident googling and getting on this page here is what I did.
1.Changed the form of CategoryByDayForm so it accepts only status and excludes day and category
forms.py
from django import forms
from today.models import CategoryByDay, Category, Day
class CategoryByDayForm(forms.ModelForm):
status = forms.CharField(max_length=64, initial="0")
class Meta:
model = CategoryByDay
exclude = ['day', 'category']
- In the template, added hidden form input sending current category iteration:
today.html
#...
{% for category, form in category_form_list %}
<li>
{{ category.name }}
<form action="" method="post">
{% csrf_token %}
{{ form.non_field_errors}}
<input type="hidden" value="{{ category.name }}" name="category">
<div class="status">
{{ form.status }}
<input type="submit" value="Submit" />
</div>
</form>
</li>
{% endfor %}
# ...
Finally, in views, I manipulated the form I got, so I added missing elements (from form I have status, I still need to set day and category)
views.py
def today(request):
t = datetime.date.today().strftime("%d/%m/%y")
day = Day.objects.filter(name=t)
if request.method == 'POST':
form = CategoryByDayForm(request.POST)
if form.is_valid():
category_status = form.save(commit=False)
category_status.day = day[0]
category_name = request.POST['category']
category_status.category = Category.objects.filter(name=category_name)[0]
category_status.save()
form.save_m2m()
...
Hope that it can help someone in the future.
Problem
So I have 2 models which relate via `Many-to-many` relationship. As I need an extra file I am using extra model `CategoryByDay` basically what I want in my application, is create a habit or everyday list that will log various things I have to do today. So I want to connect each new day with each category and record it's status (if it's done `1`, if not `0`). I am using `CharField`, because later I want to log other things as books read etc, it's not relevant here models.py ``` from django.db import models class Day(models.Model): name = models.CharField(max_length=8) date = models.DateField() def __unicode__(self): return self.name class Category(models.Model): name = models.CharField(max_length=100) categoryBD = models.ManyToManyField(Day, through='CategoryByDay') def __unicode__(self): return self.name class CategoryByDay(models.Model): day = models.ForeignKey(Day) category = models.ForeignKey(Category) status = models.CharField(max_length=64) ``` In my `html` I want to show a list of Categories and a form near it, where one will only post a status and day as well as category will be filled automatically. Now I have no idea how to do it. This is what I got so far, reading on some forum that you can pass extra data from view (This is not working, and form demands that I fill day and category form) views.py ``` def today(request): if request.method == 'POST': #... POST validation here, not relevant else: day = datetime.date.today().strftime("%d/%m/%y") categories_list = Category.objects.all() category_form_list = [] # I am doing this strange list, because later in template I had problem # accessing list through iteration like forloop.counter. # I will access it via for x,y in pair for category in categories_list: data = {'day': day, 'category': category.name,} form = CategoryByDayForm(data) #So I tried adding data to form, it didn't work and can be ignored part = [category, form] category_form_list.append(part) context = { 't': t, 'category_form_list': category_form_list,} return render(request, 'today/today.html', context) ``` This is my form, should have added it earlier I guess. forms py ``` class CategoryByDayForm(forms.ModelForm): status = forms.CharField(max_length=64, initial="0") day = forms.ModelMultipleChoiceField(queryset=Day.objects.all()) category = forms.ModelMultipleChoiceField(queryset=Category.objects.all()) class Meta: model = CategoryByDay ``` Now, in forms I am unsure what form type should I use for day and category. Maybe I should somehow omit it? Finally template: today html ``` #... <ul> {% for category, form in category_form_list %} <li> {{ category.name }} <form action="" method="post"> {% csrf_token %} {{ form.non_field_errors}} <div class="status"> {{ form.status.errors}} {{ form.status }} <input type="submit" value="Submit" /> </div> </form> </li> {% endfor %} </ul> #... ``` This works, by only showing one form `status` but when I click submit and debug it in my way, I have errors that I haven't filled day and category forms. Can someone show me how to proceed?