Django get file url - django

I want to show the URL, filename and size of the uploaded file on my site.
I tried object.file.url but it didn't work.
models.py:
file = models.FileField(upload_to="media/",null=True,blank=True, verbose_name="Files", validators=[
FileExtensionValidator(allowed_extensions=['pdf', 'docx', 'doc', 'xlsx', 'xls', 'png','jpg','jpeg'])])
And tried this but not working:
in models.py:
#property
def file_url(self):
if self.file and hasattr(self.file, 'url'):
return self.file.url

You didn't give enough information to solve this issue . Where is your views.py and templates/filename.html file code ?
Since you didn't give enough information so I try to answer your question by using another example.
Suppose your models.py file is look like in the below :
models.py
class Pic(models.Model):
name = models.CharField(max_length=255)
photo = models.FileField(upload_to="data/media/%Y/%m/%d")
def __str__(self):
return self.url
def path(self):
return self.url
And also your views.py is look like in the below:
views.py
def upload_pic(request):
documents = Pic.objects.all()
import uuid
name = uuid.uuid4().hex[:6].upper()
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
print(request.FILES)
newdoc = Pic(name=name, photo=request.FILES['docfile'])
newdoc.save()
return render(request, 'clinic/list.html', {'documents': documents, 'form': form, 'msg': 'success'})
else:
form = DocumentForm() # A empty, unbound form
return render(request, 'clinic/list.html', {'documents': documents, 'form': form})
In that case , you can show your uploaded file's url by using {{ document.photo.url }} that line of code in your template file . just check out the below example :
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li>{{ document.photo.name }}</li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}

Related

Tags are not being stored in the database even after saving form in django

views.py
def post(request):
if request.method == 'POST':
form = PostModelForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
# using the for loop i am able to save the tags data.
# for tag in form.cleaned_data['tags']:
# post.tags.add(tag)
images = request.FILES.getlist('images')
for image in images:
ImagesPostModel.objects.create(post=post, images=image)
return redirect('/Blog/home/')
else:
form = PostModelForm(request.POST)
return render(request, 'post.html', {'form': form})
models.py
class PostModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date_time = models.DateTimeField(auto_now_add=True)
title = models.TextField(null=True)
body = models.TextField(null=True)
tags = TaggableManager()
def __str__(self):
return str(self.user)
post.html
{% extends 'base.html' %}
{% block content %}
<form action="{% url 'post' %}" enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="file" multiple name="images">
<input type="submit">
</form>
{% endblock %}
After giving the input the data is stored in the tags field but, not saving in the database.
I can manually insert data through the admin panel successfully but not as a non-staff user.
I have installed taggit and placed it in the installed_apps in settings.py.
Tags are being saved using post.tags.add(tag) inside for loop. What is the issue with the code?
This is because you use commit=False for the form: then the form has no means to save the many-to-many fields. It is also not necessary to do that, you can work with:
def post(request):
if request.method == 'POST':
form = PostModelForm(request.POST)
if form.is_valid():
form.instance.user = request.user # set the user
post = form.save() # save the form
ImagesPostModel.objects.bulk_create([
ImagesPostModel(post=post, images=image)
for image in request.FILES.getlist('images')
])
return redirect('/Blog/home/')
else:
form = PostModelForm()
return render(request, 'post.html', {'form': form})
Note: Models normally have no Model suffix. Therefore it might be better to rename PostModel to Post.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Getting the uploaded images in Django

I have a class with multiple images that can be uploaded. I am trying to use Bootstrap Carousel for a slide show of the images, but I am having a hard time getting it.
Models.py
class Content(models.Model):
title = models.CharField(max_length=250)
content = models.TextField(max_length=1000)
website = models.URLField()
github = models.URLField()
def __str__(self):
return self.title
def get_image_filename(instance, filename):
title = instance.post.title
slug = slugify(title)
return "post_images/%s-%s" % (slug, filename)
class Images(models.Model):
post = models.ForeignKey(Content, on_delete=models.CASCADE)
image = models.ImageField(upload_to=get_image_filename,
verbose_name='Image')
Views.py
def home(request):
content = Content.objects.all()
name = request.POST.get('name')
email = request.POST.get('email')
message = request.POST.get('message')
if request.method == "POST":
if not name and not email and not message:
content = 'name: ' + name + '\n' + 'email: ' + email + '\n' + '\n' + message
send_mail('Email from Portfolio', content, 'email', ['email'], fail_silently=False)
messages.success(request, "Your Email has been sent")
return redirect('home')
else:
return render(request, 'appOne/home.html', {'content':content})
#login_required
def post(request):
ImageFormSet = modelformset_factory(Images,
form=ImageForm, extra=3)
#'extra' means the number of photos that you can upload ^
if request.method == 'POST':
postForm = PostForm(request.POST)
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
if postForm.is_valid() and formset.is_valid():
post_form = postForm.save(commit=False)
post_form.user = request.user
post_form.save()
for form in formset.cleaned_data:
#this helps to not crash if the user
#do not upload all the photos
if form:
image = form['image']
photo = Images(post=post_form, image=image)
photo.save()
# use django messages framework
messages.success(request,
"Yeeew, check it out on the home page!")
return HttpResponseRedirect("/")
else:
print(postForm.errors, formset.errors)
else:
postForm = PostForm()
formset = ImageFormSet(queryset=Images.objects.none())
return render(request, 'appOne/post.html',
{'postForm': postForm, 'formset': formset})
template:
{% extends 'appOne/base.html' %}
{% load static %}
{%block content%}
{% for obj in content.images_set.all %}
<img src="{{ obj.images.url}}" alt="">
{% endfor %}
{% endblock %}
</html>
Using the template above, when I tried to go home, it does not show anything.
I am in the process of showing the images. The carousel bootstrap is not yet coded on the template.
you are using wrong modelField name. replace {{ obj.images.url}} to {{ obj.image.url}}
example:
{% extends 'appOne/base.html' %}
{% load static %}
{%block content%}
{% for obj in content.images_set.all %}
<img src="{{ obj.image.url}}" alt="">
{% endfor %}
{% endblock %}
</html>

Image not being replaced when updating Django ImageField

I am working on a blog in Django and i am trying to update the image of my model BlogPost using a ModelForm.
Initialy , when creating the post, the image is being uploaded with no problems in media/posts. However , nothing happens when trying to update the existing image with another one ( or to add an image to a post already created without one).
I have found a solution online for this issue and that was to override the save() method for the model. I did that but still nothing seems to happen. Clearly, I am doing something wrong.
My code below:
views.py:
def blog_post_update_view(request,slug):
obj = get_object_or_404(BlogPost.objects.filter(user=request.user), slug=slug)
form = BlogPostModelForm(request.POST or None, instance=obj)
if form.is_valid():
form.save()
print(obj.image)
return redirect(obj.get_absolute_url()+"/detail/")
template_name = 'blog/form.html'
context = {"title": f"Update {obj.title}", "form": form}
return render(request, template_name, context)
models.py:
class BlogPost (models.Model):
# id = models.IntegerField() # pk
user= models.ForeignKey(User, default=1, null=True, on_delete=models.SET_NULL)
image=models.ImageField( upload_to='posts/',blank=True,null=True)
title=models.CharField(max_length=120)
slug= models.SlugField() # hello world -> hello-world
content=models.TextField(null=True,blank=True)
publish_date=models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True)
timestamp=models.DateTimeField(auto_now_add=True)
updated=models.DateTimeField(auto_now=True)
objects = BlogPostManager()
class Meta:
ordering = ['-publish_date', '-updated', '-timestamp']
def get_content_length(self):
return len(self.content)
def get_absolute_url(self):
return f"/blog/{self.slug}"
def get_edit_url(self):
return f"{self.get_absolute_url()}/edit"
def get_delete_url(self):
return f"{self.get_absolute_url()}/delete"
def save(self, *args, **kwargs):
try:
this = BlogPost.objects.get(id=self.id)
if this.image!= self.image:
this.image.delete()
except: pass
super(BlogPost, self).save(*args, **kwargs)
def __str__(self):
return self.title
forms.py:
class BlogPostModelForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title','image', 'slug', 'content', 'publish_date']
def clean_title(self, *args, **kwargs):
instance = self.instance
print('instance is: ',instance)
title = self.cleaned_data.get('title')
qs = BlogPost.objects.filter(title__iexact=title)
if instance is not None:
qs = qs.exclude(pk=instance.pk) # id=instance.id
if qs.exists():
raise forms.ValidationError("This title has already been used. Please try again.")
return title
blog/templates/form.html:
<!doctype html>
{% extends "blog/base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block head_title %}
{{title}}
{% endblock %}
{% block content %}
{% if title %}
<h1>{{ title }}</h1>
{% endif %}
<form method='POST' enctype="multipart/form-data" action='.'> {% csrf_token %}
{{ form|crispy}}
<button type='submit'>Send</button>
</form>
{% endblock %}
your view should be like:
def blog_post_update_view(request,slug):
obj = get_object_or_404(BlogPost.objects.filter(user=request.user), slug=slug)
if request.method == "POST":
form = BlogPostModelForm(request.POST, request.FILES, instance=obj)
if form.is_valid():
form.save()
return redirect(obj.get_absolute_url()+"/detail/")
form = BlogPostModelForm(instance=obj)
template_name = 'blog/form.html'
context = {"title": f"Update {obj.title}", "form": form}
return render(request, template_name, context)

Load the csv data using html view into django database

I am trying to load a simple csv file into django model named as class Team
class Team(models.Model):
Team = models.CharField(max_length=255,primary_key=True)
Description = models.CharField(max_length=255)
def __str__(self):
return self.Team
Views.py
def model_form_upload(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('home')
else:
form = DocumentForm()
return render(request, 'core/model_form_upload.html', {
'form': form
})
HTML
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
<p>Return to home</p>
{% endblock %}
forms.py
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ('description', 'document', )
I have create a simple html page to load the file into the following location MEDIA_ROOT=os.path.join(BASE_DIR,"media")
I am able to load my file into that location but I need some help with passing on the data to the actual database and load the values into the table "Team". Any suggestiond on this?

No Post matches the given query, allowing users to make post(django)

I'm trying to allow users to create category and post(that will be tagged to some category) I think I wrote the code right, but I'm getting 404 error with No Post matches the given query.
Here is my code.
this is my form
class CategoryForm(forms.ModelForm):
name = forms.CharField(max_length=128, help_text="aa")
likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
slug = forms.CharField(widget=forms.HiddenInput, required=False)
class Meta:
model = Category
fields =('name',)
class PostForm(forms.ModelForm):
title = forms.CharField(max_length=128, help_text="bb")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
class Meta:
model = Post
fields = ['title', 'content', 'image', 'views', 'category']
this is my view
#for adding category
def add_category(request):
if request.method == 'POST':
form = CategoryForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print form.errors
else:
form = CategoryForm()
return render(request, 'main/add_category.html', {'form':form})
#for adding post/see diff style :)
def add_post(request):
context = RequestContext(request)
if request.method == "POST":
form = PostForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit=True)
return redirect(index)
else:
print form.errors
else:
form = PostForm()
return render_to_response('main/add_post.html', {'form':form}, context)
And this is my url
url(r'^add_post/', views.add_post, name='add_post'),
url(r'^add_category/$', views.add_category, name='add_category'),
]
And finally my templates
{
% extends 'base.html' %}
{% block content %}
<form id="post_form" method="post" action="/main/add_post/" enctype="multipart/form-data">
{% csrf_token %}
{{form}}
<input type="submit" name="submit" value="Create Post">
</form>
{% endblock %}
You should use action="{% url 'main:add_post' %}" instead of action="/main/add_post/".
Also check that in your projects's urls.py main app's urls included with namespace like
url(r'^main/', include('main.urls', namespace="main"))
If you don't use namespace, than change to action="{% url 'add_post' %}".
If error reoccurs, please provide more information.
Which ulr exactly you enter in browser to get this error?
Your template makes the form post to main/add_post/ while your url for the view is add_post/. You should make them consistent.