How to bookmark a page in Django? - django

I am trying to edit an html page so a logged in user can favorite / bookmark a video.id
Here is the .html file
<td>
<form method='POST' action="{% url 'researcher_view_app:favourite_post' video.id %}">
{% csrf_token %}
<input type='hidden' name='video' value={{ video.id }}>
<button type='submit'>Bookmark</button>
</form>
</td>
Here is the urls.py file
path('<int:fav_id>/favourite_post', views.favourite_post, name='favourite_post'),
Here is the view.py file
def favourite_post(request, fav_id):
video = get_object_or_404(Video, id=fav_id)
if request.method == 'POST':
video.
return render(request, 'researcher_view_app/%s' % fav_id)

First you modify the models.py that has the user models
class ProjectUser(AbstractUser):
images = models.ManyToManyField(Images)
def __str__(self):
return self.email
In the .html file add the following:
{% for image in available_images %}
/* show image */
<form method='post' action="{% url 'user-image-add' %}">
{% csrf_token %}
<input type='hidden' name='image' value={{image.id}}>
<button type='submit'>bookmark</button>
</form>
{% endfor %}
In your views.py add the following method
def user_image_add(request):
user_image_form = ImageForm(request.POST or None)
if request.method == 'POST' and user_image_form.is_valid():
request.user.images.add(user_image_form.cleaned_data['image'])
return JsonResponse(status=200)
raise Http404()
Create a forms.py file in your add and add the following:
class ImageForm(forms.Form):
image = forms.ModelChoiceField(queryset=Images.objects.all())
To show those bookmarked images you can just iterate over request.user.images (it gives you a QS of Images) similar to code above.
In the urls.py add the following:
path('user-image-add/', views.user_image_add, 'user-image-add')
In models.py add a method in User model for getting bool if video is bookmarked
def is_bookmarked(self, video_id):
return self.bookmarked_videos.filter(id=video_id).exists()
simirlarly is_bookmarked can be added to Video model accepting user_id and checking video.projectuser_set.
And add the following to your .html file where users bookmarked a video
`{% if video.is_bookmarked %}`
Delete the UserProfile as you do not need it. Just make sure to have needed instance in context of view.

Related

Can't get Django to upload files (UPDATE: SOLVED)

I have read many questions, followed the Django docs, googled for answers, and I can't get to upload a file in my Django app.
There is no error, form.cleaned_data shows the file and the other foreign key field, but no upload to media folder and no record in my db.
I can't figure what am I missing. Any help would be much appreciated.
#models.py
class ReportFile(models.Model):
report = models.ForeignKey(Report, on_delete=models.CASCADE)
file = models.FileField(upload_to='files/reports')
uploaded = models.DateTimeField(auto_now_add=True)
uploaded_by = models.ForeignKey(User, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
user = get_current_user()
if user and not user.pk:
user = None
if not self.pk:
self.creado_por = user
###UPDATE: As Iain Shelvington kindly pointed out, I was missing the call to super.
super(ReportFile, self).save(*args, **kwargs)
#forms.py
class FileForm(forms.ModelForm):
class Meta:
model = ReportFile
fields = ['file','report']
This is the view I'm using, based on what I've read
#views.py
def CreateFile(request):
if request.method == 'POST':
form = FileForm(request.POST,request.FILES)
if form.is_valid():
form.save()
print(form.cleaned_data)
#OUTPUT: HTTP POST /file 200 [0.09, 127.0.0.1:59053]
# {'file': <InMemoryUploadedFile: test-image.png (image/png)>, 'report': <Report: 49>}
return render(request, 'segcom/file_upload.html', {'form': form,})
else:
form = FileForm()
context = {
'form':form,
}
return render(request, 'segcom/file_upload.html', context)
The relevant settings that I know of
#settings.py
# Media Root
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = '/media/'
This is the template I'm using
{% extends "layouts/base.html" %}
{% load crispy_forms_tags %}
{% block title %} File Upload Test {% endblock %}
<!-- Specific CSS goes HERE -->
{% block stylesheets %}{% endblock stylesheets %}
{% block content %}
<div class="row">
{{ form.non_field_errors }}
<form method = 'post' action="{% url 'file_upload' %}" id="report-form" enctype="multipart/form-data">
{% csrf_token %}
{{form|crispy}}
<div class="modal-footer">
<button type="submit" form="report-form" class="btn btn-primary">Guardar</button>
</div>
</form>
</div>
{% endblock content %}
<!-- Specific Page JS goes HERE -->
{% block javascripts %}
{% endblock javascripts %}

I can't post in Django

I can't post in Django, because when I import an image it doesn't work for me. it tells me that there's no file selected but I selected one.
This is the post model that I created, models.py file:
class Post(models.Model):
publisher = models.ForeignKey(User,on_delete=models.CASCADE)
caption = models.CharField(max_length=100)
date_created = models.DateTimeField(default=timezone.now())
image = models.ImageField(upload_to="post_images")
def __str__(self):
return self.caption
here's the forms.py file for the Post model:
from django import forms
from .models import Post
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['caption','image']
here's the Publish function in views.py file which implements the logic for my publish feature:
#login_required
def Publish(request):
if request.method == "POST":
form = CreatePostForm(request.POST,request.FILES)
if form.is_valid():
form.publisher = request.user
form.save()
return redirect("home")
else:
form = CreatePostForm()
return render(request,"posts/publish.html",{
"form":form,
})
int the urls.py file:
from django.urls import path
from . import views
urlpatterns = [
path('publish/',views.Publish,name="publish"),
path('',views.home,name="home"),
]
and here's in html template:
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block title %}create{% endblock title%}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-6 col-md-5 authentification">
<div class="form-header">
<h1>
publish
</h1>
</div>
<div class="form-body">
<form method="POST">
<fieldset class="form-group" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-primary form-control">publish</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
the Django version used is 2.2 and the Python 3.8. and Windows 10 Pro
You should alter the .publisher attribute of the .instance wrapped in the form, not the form itself, so:
#login_required
def Publish(request):
if request.method == 'POST':
form = CreatePostForm(request.POST,request.FILES)
if form.is_valid():
form.instance.publisher = request.user
form.save()
return redirect('home')
else:
form = CreatePostForm()
return render(request,'posts/publish.html',{
'form': form,
})
Since you are submitting both files and data, you should specify the enctype=… attribute [mdn] in the <form>:
<form enctype="multipart/form-data" method="POST">
…
</form>
Note: Django's DateTimeField [Django-doc]
has a auto_now_add=… parameter [Django-doc]
to work with timestamps. This will automatically assign the current datetime
when creating the object, and mark it as non-editable (editable=False), such
that it does not appear in ModelForms by default.
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.

how to implement drag and drop to upload files in django, while i have already implemented simple file upload

I have below code for upload file but i need to implement drag and drop functionality on top of that in django please help with my code.
upload.html
{% block content %}
<div method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="myfile"><br><br>
<input type="submit" value="upload">
{% endblock %}
Views.py
def simple_upload(request):
# return HttpResponse("<H2>Upload</H2>")
if request.method == 'POST' and request.FILES['myfile']:
myfile = request.FILES['myfile']
fs = FileSystemStorage(location="ciscotest/uploadedmedia")
filename = fs.save(myfile.name, myfile)
uploaded_file_url = fs.url(filename)
return render(request, 'upload.html', {'uploaded_file_url': uploaded_file_url,"fileupload":"File uploaded successfully"})
return render(request, 'upload.html')
All you need to do is add class="dropzone" to your form. See this answer for details:
https://stackoverflow.com/a/54654196/2606766

Inject non-form element into dynamic Django form?

Is it possible to inject a non-form element into a dynamic Django form's context? I have a "Delete user photos" form that I want to contain a thumbnail image of each user with a BooleanField checkbox and label right below it:
+------------+
| |
| photo |
| |
+------------+
[x] Delete <username>'s photos
Right now I know how to create the dynamic checkboxes and their labels but I'm not sure how to go about adding each user's photo. As can be seen from my code below, the name attribute of each HTML input tag will contain the user's ID and I'll examine this attribute when the user submits the form to determine whether to delete their photos or not. I'd like to insert an tag just above each input tag that links to the user's profile photo. The image tag's "src" attribute will contain the user's ID which creates the link to their photo. Is there a way to "inject" this non-form image tag into the context of this dynamic form in order to render an image tag just above each checkbox input tag?
Thanks.
# views.py
def remove_access_to_private_photos(request, template):
if request.method == 'POST':
form = RemovePrivatePhotoAccessForm(request.POST, this_user_id=request.user.id)
if form.is_valid():
for name, value in form.cleaned_data.items():
if value == True:
# Profile links to User via a OneToOneField
this_user = Profile.objects.get(user_id=request.user.id)
other_user = Profile.objects.get(user_id=name)
this_user.remove_private_access(other_user_prof)
return redirect('photos-home')
else:
form = RemovePrivatePhotoAccessForm(this_user_id=request.user.id)
context = {'form': form}
return render(request, template, context)
# models.py
class RemovePrivatePhotoAccessForm(forms.Form):
def __init__(self, *args, **kwargs):
this_user_id = kwargs.pop('this_user_id')
super(RemovePrivatePhotoAccessForm, self).__init__(*args, **kwargs)
user = User.objects.get(pk=this_user_id)
user_prof = Profile.objects.get(user=user)
other_user_id_list = user_prof.gave_private_access().values_list('user_id', flat=True)
for id in other_user_id_list:
other_user = User.objects.get(pk=id)
self.fields[str(id)] = forms.BooleanField(required=False)
self.fields[str(id)].label = mark_safe('%s') % (id, this_user_id, other_user.username)
# delete_photos.html
<form action="." method="post">
{% csrf_token %}
{% for field in form %}
{# I'D LIKE TO PUT <IMG> TAG HERE #}
{{ field }} Delete {{ field.label|safe }}'s photos
{% endfor %}
<input type="submit" value="Submit" />
</form>
A form field is just a class, so you can add whatever properties you need when or after you instantiate it. Your view remains unchanged given this example code.
# forms.py
from .models import Profile # or whatever
class RemovePrivatePhotoAccessForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user_id')
user_profile = Profile.objects.get(pk=user_id)
other_profiles = user_profile.gave_private_access()
for profile in other_profiles:
id = str(profile.id)
field = forms.BooleanField(required=False)
field.label = mark_safe('%s') % (id, user_profile.id, profile.username)
field.photo = profile.photo
self.fields[id] = field
super(RemovePrivatePhotoAccessForm, self).__init__(*args, **kwargs)
# delete_photos.html
<form action="." method="post">
{% csrf_token %}
{% for field in form %}
<img src="{{ field.photo.url }}" />
{{ field }} Delete {{ field.label|safe }}'s photos
{% endfor %}
<input type="submit" value="Submit" />
</form>
Here's how I solved this problem. First I created a custom template tag:
# photos/templatetags/photos_extras.py
from django import template
from django.contrib.auth.models import User
from django.utils.safestring import mark_safe
register = template.Library()
#register.simple_tag
def render_image(uid):
user = User.objects.get(pk=uid)
src_string = ''.join([
'/photos/',
user.username, '_',
user.profile.image_id,
'_thumb.jpg'])
img_tag = ''.join([
'<img src="',
src_string,
'" alt="',
user.username,
'" />'])
return mark_safe(img_tag)
I then inserted the custom template tag into my template. field.name contains the desired user's user ID, and render_image returns the desired HTML img tag.
# delete_photos.html
<form action="." method="post">
{% csrf_token %}
{% for field in form %}
{% render_image field.name %}
{{ field }} Delete {{ field.label|safe }}'s photos
{% endfor %}
<input type="submit" value="Submit" />
</form>

Django Model Form Image Field Does Not Validate

I am writing a simple view using Django Model Form, however image field fails to validate with 'This field is required' error message.
I wonder where the problem is...
Model:
class Deal(AbstractModel):
IMAGE_MAX_LENGTH = 200
place = models.ForeignKey(Place, related_name='deals', related_query_name='deal', verbose_name=_("Place"))
image = models.ImageField(default='deals/default.png', max_length=IMAGE_MAX_LENGTH, upload_to='deals', verbose_name=_("Image"))
...
View:
#login_required
def deals_create(request):
# Get place id
place_id = request.GET.get('place')
# Get place
place = Place.objects.get(id=place_id)
# Process form data
if request.method == 'POST':
form = DealsCreateForm(request.POST, request.FILES)
# Validate post data
if form.is_valid():
# Save deal data
deal = form.save(commit=False)
deal.place = place
deal.save()
# Redirect to reload page and clear post data
return HttpResponseRedirect(reverse('deal_manager:deals_pending'))
else:
form = DealsCreateForm()
return render(request, 'deal_manager/deals_create.html', {
'form': form,
'place': place,
})
Form:
class DealsCreateForm(ModelForm):
class Meta:
model = Deal
fields = [
'image', 'product_name', 'product_description',
'regular_price', 'sale_price', 'limit', 'terms',
]
Template:
{% extends "deal_manager/deal_manager.html" %}
{% load i18n %}
{% load staticfiles %}
{% block page_content_body %}
<div class="row">
<div class="span12">
<form action="{% url 'deal_manager:deals_create' %}?place={{ place.id }}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="{% trans 'Create' %}" />
</form>
</div>
</div>
<div class="gap gap-small"></div>
{% endblock page_content_body %}
Note: Form validates when I remove the image field from form meta fields.
Note: File uploads works fine with Django Admin for this model.
You'll need to include enctype="multipart/form-data" in order to bind imagefield and filefield data to the form. Without that, those fields won't validate.
{% block page_content_body %}
<div class="row">
<div class="span12">
<form enctype="multipart/form-data" action="{% url 'deal_manager:deals_create' %}?place={{ place.id }}" method="post">
...
Here's the relevant documentation: https://docs.djangoproject.com/en/stable/ref/forms/api/#binding-uploaded-files-to-a-form