I want to upload multiple images.
class IssuePanel(models.Model):
issue = models.ForeignKey(ComicIssue, on_delete=models.CASCADE)
panel = models.FileField(upload_to='comic_issues_files/panels/')
date_uploaded = models.DateTimeField(auto_now_add=True)
After following the examples on django-multiupload's repository on github, I have this on forms.py
class PanelsForm(forms.ModelForm):
class Meta:
model = ComicIssue
fields = ('issue', 'issue_title', 'issue_cover', 'issue_description', 'issue_cover', 'issue_file')
panels = MultiFileField(min_num=1, max_num=20, max_file_size=2048*2048*5)
def save(self, commit=False):
instance = super(PanelsForm, self).save()
for each in self.cleaned_data['panels']:
IssuePanel.objects.create(panel=each, issue=instance)
return instance
views.py
class ComicIssueCreate(LoginRequiredMixin, CreateView):
model = ComicIssue
slug_field = 'comicseries_id'
form_class = PanelsForm
def form_valid(self, form):
obj = form.save(commit=False)
obj.title = ComicSeries.objects.get(id=self.kwargs['pk'])
obj.user = self.request.user
obj.save()
return redirect('comics:series_detail', pk=obj.title.id, slug=obj.title.slug)
urls.py
url(r'^comic/issue/(?P<pk>[0-9]+)/add/$', views.ComicIssueCreate.as_view(), name='comic-issue-add'),
However, I get this error IntegrityError at /comic/issue/21/add/ NOT NULL constraint failed: comics_comicissue.title_id
class ComicIssue(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,
null=True, blank=True, verbose_name='Uploaded by: '
)
title = models.ForeignKey(ComicSeries, on_delete=models.CASCADE, verbose_name='Series Title')
issue = models.CharField(verbose_name='Issue Number', max_length=500)
issue_title = models.CharField(verbose_name='Issue Title', max_length=1000)
issue_cover = models.ImageField(verbose_name='Issue cover', upload_to='comic_issues', height_field=None, width_field=None, max_length=None)
issue_description = models.TextField(verbose_name='Description')
issue_file = models.FileField(verbose_name='Issue file', upload_to='comic_issues_files', max_length=100,
help_text='File in pdf or as single image', null=True, blank=True
)
date_added = models.DateTimeField(auto_now_add=True, null=True)
is_favorite = models.BooleanField(default=False)
issue_slug = models.SlugField(default='')
class Meta:
verbose_name = 'Comic Issue'
verbose_name_plural = 'Comic Issues'
def __str__(self):
return '{}: {} issue number - {}'.format(self.title.title, self.issue_title, self.issue)
def save(self, *args, **kwargs):
self.issue_slug = slugify(self.issue_title)
super(ComicIssue, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('comics:issue_detail', kwargs={'issue_slug':self.issue_slug,'pk': self.pk})
Could this function in the ComicIssue model be a problem since it is also highlighted on the error page:
def save(self, commit=False, *args, **kwargs):
self.issue_slug = slugify(self.issue_title)
super(ComicIssue, self).save(*args, **kwargs)
I am passing the title_id from the url. It is working on other models just not this one. How do I save the foreign key?
You're saving your form in the form's save
method regardless of the commit
value. The first line is instance = super(PanelsForm, self).save()
which will try to save a ComicIssue
instance even though in your view, you wrote obj = form.save(commit=False)
.
You can do two things: pass the title
and user
to your form at init so the form can handle assigning those during save. Or change your form's save
method to:
def save(self, commit=False):
instance = super(PanelsForm, self).save(commit=commit)
if commit:
for each in self.cleaned_data['panels']:
IssuePanel.objects.create(panel=each, issue=instance)
return instance
And then your view needs to call the form's save()
method twice (note that the form's instance
is passed by reference, so changing it in the view also changes the form's instance
):
def form_valid(self, form):
obj = form.save(commit=False)
obj.title = ComicSeries.objects.get(id=self.kwargs['pk'])
obj.user = self.request.user
form.save()
return redirect('comics:series_detail', pk=obj.title.id, slug=obj.title.slug)