Hi Robert,
On 18/01/07, Robert <[EMAIL PROTECTED]> wrote:
I know newforms are still in development, but maybe there are known practiced on how to manage custom Form. Let's say there's a model: ITEM_TYPE_CHOICES = ( ('new','new'), ('used','used') ) class Item(models.Model): owner = models.ForeignKey(Users) (maybe this should not be here so it's not displayed at all?) name = models.CharField(blank=False, maxlength="20") type = models.CharField(maxlength="4", blank=False) Here's the class Form: class AddEditItemForm(forms.Form): owner = ChoiceField(choices=[('','-------')]+[(o.id,o.email) for o in User.objects.all()]) name = CharField() type = CharField() (I have ommited maxlength etc. for simplicity). How shold the create/update view look like? I would like to use {{ form.owner }} , {{ form.name }} in my template.
If you just want form.owner and form.name then you can drop 'type' from the form definition.
Some are using: def create_edit_item(request, object_id): if object_id is None: item = Item.objects.get(id=object_id) ItemForm = AddEditForm(initial=item.__dict__) else: ItemForm = AddEditForm() problem 1: item.__dict__ returns a dict with: owner_id value instaed of owner, initial won't work then if using owner_id in the AddEditForm() it looks messy in the template (name=id_owner_id). I know form_for_instance produces form with "owner" field name, not owner_id.
using item.__dict__ will not work properly for ForeignKeys and M2M fields. It's better to pass the instance into the Form and do the magic yourself (see below for an example).
I know there are some problems with form_for_model.save() yet.. and that I have to manipulate form.clean_data and use object.save() instaed, but how should my view If I want just edit name & type so that the user won't be asked to enter / won't be able to POST "owner" value.
To do this I'd leave the owner field out of the form, define a save method for your form (which will return an appropriate instance) and then update the instance with request.user or whatever.
Can anybody please explain how should my add/edit view & form look like assuming the newly created item owner gets the request.user & that when editing this can't be changed by anyone?
To ensure that no-one can change the owner field make sure you set the value yourself in the view and ignore anything passed in by the user.
Or maybe I can use form_for_instance, but I have no idea how can I "cut off" some fields so they are not in this form. That's just a thought. I've considered the example from: http://groups.google.com/group/django-users/browse_frm/thread/d9e03cf29739869f/71c60c65387802bc?lnk=gst&q=newforms&rnum=8#71c60c65387802bc but I'd rather avoid using hiddenfields. Also I need to use {{ form.name }} instead of {{ form }}.
Right. Below I've inserted a little write up I've been working on. What I've described works for me. YMMV. (I'd appreciate comments if anyone has any). Django Newforms =============== Binding a form to a model instance ---------------------------------- Django's newforms module provides the helper method 'form_for_instance'. The method will return a Form similar to the one returned by form_for_model but the initial data will be populated by the instance's data. The form will have a 'save' method which will save changes to the instance to the database (unless it is passed the commit=False argument) and will return the instance itself. Sometimes, however, it is desirable to use fields different from the default. In order to bind a form to an instance one will have to provide __init__ and save methods. The __init__ method should be defined as follows: def __init__(self, data=None, auto_id='id_%s', prefix=None, initial=None, instance=None): if instance is not None: self.instance = instance new_data = {} # Populate new_data using 'instance' # ... data = new_data else: self.instance = None super(MyForm, self).__init__(data, auto_id, prefix, initial) The __init__ method will save the original instance in self.instance and pass the data it contains to the superclass (most likely forms.Form). The bound form will be created with MyForm(instance=MyInstance). To use the form for creating new instances it can be created with MyForm(request.POST). The save method will look similar to the following: def save(self, commit=True): if self.instance is not None: instance = self.instance else: instance = InstanceModel() # Construct the instance below using self.clean_data # Using self.clean_data ensures everything is validated. # ... if commit: instance.save() return instance It should be noted that one will not be able to save ManyToMany data without saving the instance first. If the model contains M2M fields then commit=False will not make any sense. Views ----- Your add+edit view should look something like the following: def add_edit_model(request, id=None): if id is not None: instance = MyModel.objects.get(id=id) InstanceForm = MyForm(instance=instance) else: InstanceForm = MyForm() if request.POST: form = InstanceForm(request.POST) if form.is_valid(): form.save() return HttpResponseRedirect('/whatever/url/') return render_to_response('template.html', {'form': InstanceForm}) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---