UPDATE: I created a github repo with a full site demonstration of the problem. Maybe my description below isn't quite communicating what I'm trying to do.
The github repo is: https://github.com/theCodeJerk/m2m-through
The code below is stripped down to illustrate the issue. While there are things that you may want to say "why would you do this anyway", there is probably a reason in the larger context :)
Here is my view:
class SubmissionCreate(CreateView):
model = Submission
fields = '__all__'
template_name_suffix = '_create_form'
success_url = '/'
Here is the relevant models.py code:
def custom_filename(instance, filename):
author = instance.publishers[0]
return 'papers/{0}.pdf'.format(author.pseudonum)
class Submission(models.Model):
name = models.CharField(
max_length=200,
blank=False
)
upload = models.FileField(
blank=True,
upload_to=custom_filename
)
publishers = models.ManyToManyField(
'Publisher',
blank=False,
related_name='publisher_of',
through='SubmissionPublisher'
)
class Publisher(models.Model):
user = models.ForeignKey(
User, blank=False,
on_delete=models.CASCADE
)
pseudonym = models.CharField(
max_length=200,
blank=False
)
class SubmissionPublisher(models.Model):
publisher = models.ForeignKey(
'Publisher',
blank=False,
on_delete=models.CASCADE
)
submission = models.ForeignKey(
'Submission',
blank=False,
on_delete=models.CASCADE
)
The problem is in the custom_filename, because I need the first publisher from the instance to generate the filename. The Submission is not yet saved when the SubmissionPublisher needs it to be saved.
What would the best way to do this be. Hopefully I have made sense here.
Thanks for any help!
Probably you can try like this:
First, update your custom_filename method:
def custom_filename(instance, filename):
if instance:
authors = instance.publishers.all()
if authors.exists():
author = authors[0]
return 'papers/{0}.pdf'.format(author.pseudonum)
return filename
Here I have fixed few issues, for example in your code instances.publishers[0] won't work, because you need to use a queryset method(like all(), or filter() etc) to access Publisher instances.
Then, make upload field nullable. Because you can't create M2M relations without creating Submission instance, and you can't create Submission instance with upload not null, because it requires an image.
class Submission(models.Model):
name = models.CharField(
max_length=200,
blank=False
)
upload = models.FileField(
null=True, default=None,
blank=True,
upload_to=custom_filename
)
Then, create a Form and override the save method:
from django import forms
from .models import Submission
class SubmissionForm(forms.ModelForm):
class Meta:
model = Submission
fields = '__all__'
def save(self, commit=True):
uploaded_file = self.cleaned_data.pop('upload')
instance = super().save(commit=True)
instance.upload = uploaded_file
instance.save()
return instance
Here I am pulling out the value for upload and saving the instance first. Then putting the image later. This code will work because upload field is nullable in your Submission model.
Finally, use that form class in your SubmissionCreate view:
class SubmissionCreate(CreateView):
model = Submission
form_class = SubmissionForm
template_name_suffix = '_create_form'
success_url = '/'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With