many to many field in django is working in admin site but not in front end site form

Question:

In my code CreateNoticeForm is working fine and all data gets saved perfectly except
many to many field which is tags in my notice model.Although it is working on admin site and gets saved.

here is my code
models.py

from django.db import models
from django.contrib.auth.models import User

from wysihtml5.fields import Wysihtml5TextField

# Create your models here.
class Tag(models.Model):
    # For notice tags
    name = models.CharField(max_length=70, unique=True)

    def __str__(self):
        return self.name


class Notice(models.Model):
    # Notice Store
    headline = models.CharField(max_length=140)
    description = Wysihtml5TextField()
    file_name = models.FileField(upload_to='static/noticefiles/', blank=True)
    created_by = models.ForeignKey(User)
    fors = models.CharField(max_length=1, choices=(('F','Faculty'),('S','Student'),) )
    last_date = models.DateField()
    tags = models.ManyToManyField(Tag, blank=True)
    post_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.headline

forms,py

FORS_CHOICES = (('F','Faculty'),('S','Student'))


class CreateNoticeForm(ModelForm):
    fors = forms.ChoiceField(label="Related To",
                             choices=FORS_CHOICES,
                            )
    class Meta:
        model = Notice
        fields = ('headline', 'description',
                  'fors', 'last_date', 'tags','file_name')
        widgets = {
            'description': Wysihtml5BootstrapWidget(),
            'last_date': SelectDateWidget()
        }
    def __init__(self, *args, **kwargs):
        super(CreateNoticeForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_id = 'create_notice_form_id'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_method = 'post'
        self.helper.label_class = 'col-lg-2'
        self.helper.field_class = 'col-lg-8'
        self.helper.layout = Layout(
            Fieldset('Create Notice',
                     'headline', 
                     'description',
                     Field('fors', label='Audience'),
                     MultiWidgetField('last_date',
                        attrs=(
                            {'style': 'width: 33.33%; display: inline-block;'}
                        )
                     ),
                     'tags',
                     'file_name',
                     FormActions(
                        Submit('save', 'Create Notice', 
                        css_class='btn-warning col-lg-offset-2'),
                     ),
            ),

views.py

def create_notice(request):

    context = RequestContext(request)

    posted = False

    if request.method=='POST':
        create_notice_form = CreateNoticeForm(data=request.POST, files=request.FILES)

        if create_notice_form.is_valid():
            cnf = create_notice_form.save(commit=False)
            cnf.created_by = request.user
            cnf.save()
            posted = True
        else:
            print(create_notice_form.errors)

    else:
        create_notice_form = CreateNoticeForm()


    return render_to_response('notices/createnotice1.html',
                              {'create_notice_form': create_notice_form,
                               'posted': posted,},
                              context)
Asked By: Sinu Poonia

||

Answers:

You have to call save_m2m():

cnf = create_notice_form.save(commit=False)
cnf.created_by = request.user
cnf.save()
create_notice_form.save_m2m()

Excerpt from the documentation:

If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.

To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.

Answered By: catavaran

You have to Call the following after validating the form:-

if create_notice_form.is_valid():
    parent = create_notice_form.save(commit=False) 
    parent.save() 
    create_notice_form.save_m2m()

I hope this will help you

Answered By: Coding India
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.