2đź‘Ť
So, let’s go.
When you set a ImageField()
, you have a upload_to
attribute. From the documentation:
A local filesystem path that will be appended to your MEDIA_ROOT setting to determine the value of the url attribute.
So you will have a function to determine a dynamic path where the image will be stored (read the link above for more information).
E.g.
class Post(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length = 200)
text = models.TextField()
model_pic= models.ImageField(upload_to=upload_image, default='blog/images/already.png')
created_date = models.DateTimeField(default = timezone.now)
published_date = models.DateTimeField(blank = True, null =True)
def upload_image(self, filename):
return 'post/{}/{}'.format(self.title, filename)
Note that you don’t include the model_pic
in your fields
of the PostForm. So it will not appear on the template.
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'text', 'model_pic',)
Your view will change a little bit:
@login_required
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST, request.FILES)
Once you’re using an upload, you will use the request.FILES read more here, but let me quote this:
Note that FILES will only contain data if the request method was POST and the that posted to the request had enctype=”multipart/form-data”. Otherwise, FILES will be a blank dictionary-like object.
So on your template, your tag <form>
will have a attribute enctype="multipart/form-data"
<form enctype="multipart/form-data" method="POST" action="">
{{ form.as_p }}
</form>
After all, you can retrieve this image to show in a page. Assuming that you have passed a post
instance via context to the template:
<img src="{{ post.model_pic.url }}" alt="{{ post.title }}" />