1. django one form, two models

    This post is a work in progress is now working I am glad to say. I have been working on a django site which needs two models updated for one post. It is actually using models very close to that on django-forums and I have created a forms.py file:

    class ThreadForm(forms.ModelForm):
        class Meta:
            model = Thread
            exclude = ('forum', 'sticky', 'closed', 'posts', 'views', 'latest_post_time')
         
        def clean_title(self):
            title = self.cleaned_data['title']
            if not alnum_re.search(title):
                raise forms.ValidationError(ugettext("Titles can only contain letters, numbers and underscores"))

            if len(title) < 1:
                raise forms.ValidationError(ugettext("Please enter a title"))
            return title

           
    class PostForm(forms.ModelForm):
        class Meta:
            model = Post
            exclude = ('thread', 'author', 'time', 'related_item')
           
        def clean_body(self):
            body = self.cleaned_data['body']
            if len(body) < 1:
                raise forms.ValidationError(ugettext("Please enter some body text"))
            return body

    And then in my views (after importing in the correct models):

    @login_required
    def groupnewthread(request, slug):
        thegroup = get_object_or_404(GroupsOfUser, slug=slug)
        if request.method == 'POST':
            f = request.POST.copy()
            tdata = {
                'title': f['title'],
            }
            pdata = {
                'body': f['body'],
            }
            t = ThreadForm(tdata)
            p = PostForm(pdata)
            if t.is_valid():
                newthread = t.save(commit=False)
                newthread.forum = thegroup
               
               
                if p.is_valid():
                    newthread.save()
                    newpost = p.save(commit=False)
                    newpost.thread = newthread
                    newpost.author = request.user
                    newpost.save()
             
                    strmessage = 'has created a thread <a href="%s">%s</a>' % (newthread.get_absolute_url(), newthread.title)
                    usm = UserStatus(user = newpost.author, message = strmessage)
                    usm.save()
             
                    return HttpResponseRedirect(reverse('groupdetail', args=[thegroup.slug]))
           
        else:

            t = ThreadForm()
            p = PostForm()
           
        objContext = RequestContext(request, {'threadform': t, 'postform': p})
        return render_to_response('groups/group_thread_add.html', objContext)

    Now the bit that is in progress is the returning part of dealing with the form data being bound, but I am going to write a custom handler. This is obviously going to be much easier to handle than an update, which I will have to deal with at a point.

    The form HTML looks like this btw:

    {% extends "base.html" %}
    {% load i18n %}
    {% block title %}
        {% trans 'Add a new group thread' %}
    {% endblock %}
    {% block body %}
        <h1>{% trans 'Create a new group thread' %}</h1>
    <div class="column span-14">
        {% if t.errors %}
        <h3>{% blocktrans count t.errors|length as count %}Please correct the following error:{% plural %}Please correct the following errors:{% endblocktrans %}</h3>
        {% endif %}
        {% if p.errors %}
        <h3>{% blocktrans count p.errors|length as count %}Please correct the following error:{% plural %}Please correct the following errors:{% endblocktrans %}</h3>
        {% endif %}
        <table>
        <form method="post" action=".">
            {{ threadform.as_table }}
            {{ postform.as_table }}
        <tr><td></td><td><input type="submit" value="{% trans "Update" %}"/></td></tr>
        </form>
        </table>
    </div>
    {% endblock %}
    By timc3 on the
    June 21st, 2008

4 Comments

  1. The code and explanation are somewhat unreadable (mac os x, ff3). The code is not indented (big unreadability in python), nor colored. The bottom of the post looks like something went wrong…there is a button that says ‘{% trans’…

    I’m not sure you have a great solution to the two model, one form problem. Seems like you’ve just hard-coded your view to refer to a single form. Maybe you want to invest in inheritance or a formset.

    It’s a tough problem. Good luck.

    anon Says:
    September 22nd, 2008 at 2:49 pm
  2. Sorry for the unreadable code. I am going to update the design ASAP.

    timc3 Says:
    January 20th, 2009 at 2:00 pm
  3. I have now updated the page so you should be able to read the code!

    timc3 Says:
    February 2nd, 2009 at 5:00 pm
  4. Very good one, saved me time ;D

Please post a comment