简体   繁体   中英

Django formset with no initial data

I am a Django rookie and I am developing a small app to register time (duration) and quantity of activities per user per day. Sort of like a work log. My problem is this: My “add entry” view displays and updates old records rather than adding new records to the db. I need a view to add new records, not replace old ones.

From searching around and from the #django IRC channel, I understand that the formset-way by default draws on old data rather than setting the client up for adding new data. I have, however, not found anything about how to avoid this behaviour and have the client provide a blank form for "appending new data" rather than "editing existing data".

My deadline is drawing really close and all help is greatly appreciated.

Here are the relevant code snippets:

From models.py

class Activity(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()

class Workday(models.Model):
    entrydate = models.DateField()
    worker = models.ForeignKey(User, on_delete=models.CASCADE)

class Entry(models.Model):
    duration = models.DurationField()
    quantity = models.PositiveIntegerField()
    activity = models.ForeignKey(Activity, on_delete=models.CASCADE)
    workday = models.ForeignKey(Workday, on_delete=models.CASCADE)

From forms.py

class EntryForm(ModelForm):
    activity = ModelChoiceField(queryset=Activity.objects.order_by('name'), initial=0)

    class Meta:
        model = Entry
        fields = ['activity',
                  'duration',
                  'quantity',
                  ]

class WorkdayForm(ModelForm):
    class Meta:
        model = Workday
        fields = ['entrydate']
        widgets = {'entrydate': SelectDateWidget}

From views.py

def addentry(request):
    EntryFormSet = modelformset_factory(Entry, form=EntryForm, extra=0, fields=('activity', 'duration', 'quantity'))

    if request.method == 'POST':
        workdayform = WorkdayForm(request.POST, prefix='workday')
        formset = EntryFormSet(request.POST)

        if formset.is_valid() and workdayform.is_valid():
            # Generate a workday object
            workday = workdayform.save(commit=False)
            workday.entrydate = workdayform.cleaned_data['entrydate']
            workday.worker = request.user
            workday.save()

            # Generate entry objects for each form in the entry formset
            for form in formset:
                e = form.save(commit=False)
                e.workday = workday
                e.save()
                form.save_m2m()

                messages.add_message(request, messages.SUCCESS,
                                     "Registrert aktivitet " +
                                     e.workday.entrydate.strftime('%A %d. %B %Y') +
                                     ": " + e.activity.name + " (" + str(e.quantity) +") - " +
                                     str(e.duration)
                )

            return redirect('index')
        else:
            workdayform = WorkdayForm(request.POST, prefix='workday')
            formset = EntryFormSet(request.POST)

            for dict in formset.errors:
                messages.add_message(request, messages.ERROR, dict)

            context = {
                       'workdayform': workdayform,
                       'formset': formset,
                       }
            return render(request, 'register/addentry.html', context)

    else:
        workdayform = WorkdayForm(prefix='workday')
        formset = EntryFormSet()
        context = {
                   'workdayform': workdayform,
                   'formset': formset,
                   }
        return render(request, 'register/addentry.html', context)

From addentry.html

{% block content %}
    {% if user.is_authenticated %}

        <h1>Ny dag</h1>
        {% if formset and workdayform %}
            <form id="newdayform" method="POST" class="post-form">
                {% csrf_token %}

                {{ workdayform.as_p }}

                {{ formset.management_form }}

                <table>
                    <thead>
                        <tr>
                            <td>Aktivitet</td>
                            <td>Varighet<br/>(HH:MM:SS)</td>
                            <td>Antall</td>
                        </tr>
                    </thead>
                    <tbody>
                        {%  for form in formset %}
                            <tr>
                                <td>{{ form.activity }}</td>
                                <td>{{ form.duration }}</td>
                                <td>{{ form.quantity }}</td>
                                <td class="hidden">{{ form.id }}</td>
                            </tr>
                        {% endfor %}
                    </tbody>
                </table>
                <button type="submit">Registrer tid</button>
            </form>

               <script src="{% static 'register/jquery.formset.js' %}"></script>
    <script type="text/javascript">
        $(function() {
            $('#newdayform tbody tr').formset();
        })
    </script>

            {% if entryform.errors or workdayform.errors %}
                <h3>Feil i utfyllingen</h3>
                {{ entryform.errors }}
                {{ workdayform.errors }}
            {% endif %}

        {% else %}
            <p>No form!</p>
        {% endif %}

    {% endif %}
{% endblock %}

Thanks to @e4c5 and this previous Q&A , the issue is solved by passing a queryset of no objects to the formset, like this:

def addentry(request):
    (...)

    qs = Entry.objects.none()
    formset = EntryFormSet(queryset=qs)

   (...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM