开发者

How much can django.forms help me?

I have the following model which forms a Many-To-Many relationship between Persons and "Eprint" publications. Each person's profile page will show the eprints referenced through this table, but only if show=True, and in the numeric order of the 'order' field:

class UsersEprint(models.Model):
    person = models.ForeignKey(Person)
    eprint = models.ForeignKey(emodels.Eprint) # th开发者_如何学编程is has a .title field
    show = models.BooleanField(default=True)
    order = models.IntegerField(default=0)

Now this can all be managed from the admin, but I want a user-friendly form to go in the users profile page on the site.

Ideally I want a table with a row for each of the person's eprints, giving: the eprint title (which can't be edited), a tickbox for 'show', and a numeric field for 'order'. A 'delete' tickbox would be useful too.

The default approach with modelformsets gives a dropdown chooser for the eprint listing all the eprints - which is because the form doesn't know I don't want to edit this. I've tried various approaches with overriding fields and widgets but it all seems a bit kludgy, and I'm going to have end up rendering the form in the template line-by-line anyway, it seems.

The next complication is that instead of having the user type numbers to reorder the table rows, I could use a javascript system - either drag'n'drop rows or move up/move down arrows. When the user submits the form, the new order is obtained.

My question is, at what point do I go out of the scope of django's form handling? Should I just drop import django.forms and manage it all myself? Or are there still useful bits in there for even the most awkward forms?


I don't think your use case is particularly awkward, and I'm sure an InlineModelFormset can handle all your requirements nicely. The thing to remember, is that the primary concern of Django forms is the validation of input data; the presentation is (and should be) up to you.

Sure, Django provides some basic tools for form layout (as_ul et al), but you shouldn't get too hung up on them. Customizing the way your forms are rendered shouldn't be viewed as a "hack", but a feature ;-)

  1. Since you won't be editing the eprint, you can exclude this field from the underlying form, which you pass to inlinemodelformset_factory; in your template, just display form.instance.eprint.title instead of form.eprint (form.instance points to the underlying model instance)

  2. When rendering the forms in the formset, you can check form.instance.show -- if it's True, then render the form normally. Otherwise, either add a "hidden" class to the form's container, or render the fields as hidden inputs (form.<FIELD>.as_hidden). Unfortunately, you can't simply omit them, as that would cause validation errors on the server

  3. Passing can_delete=True to inlinemodelformset_factory will add a -DELETE checkbox to each form; you can use jQuery to hide this, and instead render a delete button. When clicked, the button sets the value of the checkbox, and Django handles the rest. You can see an example of this here

  4. The ordering can be handled using a toolkit like jQuery UI -- take a look at this snippet for ideas. Again, progressive enhancement is what you're after here; all your script would do is update the order field, and let Django handle the actual saving when you submit. That way, the functionality is still present, even if Javascript is disabled (or absent) on the client

Don't be afraid to explore and experiment. Not all of Django is documented, yet (use the source, Luke :) If you're worried about depending on a feature that might be removed sometime in the future, you can always ask on Django Users


There's no "good" answer to this question, but personally I'd say this is out of scope;) As you say yourself, you can control the types of fields rendered in various manors, but they, I agree, do make it feel "kludgy".

Also, have you thought about the html behind your javascript system? What kind of form would you need with that... How would a view handle that if it was expecting a form rendered by Django's form handling. You could probably do it, but I think it would get real ugly real fast.

I think you'd be better of designing a template with the form from scratch, and a handling view as well. Unfortunately it will cost you extra work to do validation, but I think you will win more time making the form do exactly what you want it to do.

Let me repeat, this is really advise, I'm sure you could use the standard form handling, but I wouldn't if I had to do the same thing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜