Django song not being added to 'favourite songs' - django

I want my users to be able to add certain songs to Favourite Songs but although the success message 'Added to favourite songs' but when I visit the Favourite Songs page, I see no songs there. How can I fix this? Thanks in advance!
My models.py:
class Songs(models.Model):
title = models.CharField(max_length = 100)
lyrics = models.TextField()
author = models.CharField(max_length = 100)
track_image = models.CharField(max_length=2083)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('/', kwargs={'pk': self.pk})
My views.py:
def home(request):
context = {
'songs': Songs.objects.all()
}
return render(request, 'home.html', context)
#login_required
def add_to_fav_songs(request, **kwargs):
fav_song = Songs.objects.filter(id=kwargs.get('id'))
messages.success(request, f'Added to favourite songs')
return redirect('/')
class Fav_songs(ListView):
model = Songs
template_name = 'fav_songs.html'
context_object_name = 'fav_song'
paginate_by = 2
def get_queryset(self):
return Songs.objects.filter(pk=self.kwargs.get('pk'))
My favoutie_songs.html:
{% for song in fav_song %}
<article class="media content-section">
<div class="media-body">
<h2><a class="article-title" href="{% url 'song-detail' song.id %}">{{ song.title }}</a></h2>
<div class="article-metadata">
<a class="mr-2" href="{% url 'author-songs' song.author %}">{{ song.author }}</a>
</div>
<br>
<img class="card-img-bottom" height="339px" width="20px" src="{{ song.track_image }}">
</div>
</article>
{% endfor %}

Your Song is not connected to the User, so you never keep track about what user has wat song as favorite.
You should add a ManyToManyField to your Song model with:
from django.conf import settings
class Songs(models.Model):
# …
favorited_by = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='favorite_songs'
)
# …
Then in our view we can add the logged in user to the favorited_by field. Since we here alter data, this should be done with a POST request:
from django.contrib.auth.decorators import loginrequired
from django.shortcuts import get_object_or_404
from django.views.decorators.http import require_http_methods
#login_required
#require_POST
def add_to_fav_songs(request, pk):
fav_song = get_object_or_404(Songs, id=pk)
fav_song.favorited_by.add(request.user)
messages.success(request, 'Added to favourite songs')
return redirect('/')
For the ListView, we can then filter by the logged in user:
from django.contrib.auth.mixins import LoginRequiredMixin
class Fav_songs(LoginRequiredMixin, ListView):
model = Songs
template_name = 'fav_songs.html'
context_object_name = 'fav_song'
paginate_by = 2
def get_queryset(self):
return Songs.objects.filter(favorited_by=self.request.user)
You should change the button to add this to the favorite to a miniform:
<form method="post" action="{% url 'add-to-fav-songs' song.id %}">
<button class="btn btn-danger" type="submit">Add to Favorite Songs</button>
</form>
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin mixin [Django-doc].

Related

get() got an unexpected keyword argument 'title'

i want to fetch a blog with a model field which is unique and but when i click on a perticular blog it throw me above mentioned error
here is my views
class Blogs(View):
def get(self, request):
blog_list = Blog.objects.order_by('-joined_date')
return render(request, 'blogs.html',{'blog_list':blog_list})
class ReadBlogs(View):
def get(self, request, title):
readblog = Blog.objects.filter(title=title)
return render(request,'blogs_read.html', {'readblog':readblog})
my model
class Blog(models.Model):
title = models.CharField(max_length=48, blank=False)
urltitle = models.SlugField(max_length=48, blank=False, unique=True)
title_image = models.ImageField(upload_to='blog',blank=True, null=True)
subone = models.CharField(max_length=80, blank=False)
subone_image = models.ImageField(upload_to='blog',blank=True,null=True)
onedes = models.TextField(blank=False)
my html for fetching right blog
<div class="blogs">
{% for blogs in blog_list %}
<a class="products" href="{% url 'blogs:readblog' title=blogs.urltitle %}">
<div class="blog col-4" style="width: 18rem; height:350px">
<img class="img" src="{{ blogs.title_image.url }}" alt="" height="250px" width="100%">
<div class="detail">
<h4 class="title text-center" style="color: #025; font-family:cursive;">{{blogs.title}}</h4>
</div>
</div>
</a>
{% endfor %}
</div>
my url.py
urlpatterns = [
path('blogs/',Blogs.as_view(),name="Blogs"),
path('<slug:title>/',ReadBlogs.as_view(),name="readblog")
]
as you can see mu urltitle is unique slug field so but when i clicked on a particular blog i got above mentioned error any idea what causing error
my template for showing realated field of that blog
<div class="col-11 card">
<div class="blogs">
{% for blog in readblog %}
<h1 class="text-center" style="color: #025; font-family:cursive; margin-top:20px;">{{read.title}}</h1>
{% endfor %}
</div>
</div>
The URL parameter is named title, not url_title:
path('<slug:title>/',ReadBlogs.as_view(),name='readblog')
therefore the .get(…) method should work with title as parameter:
class ReadBlogs(View):
# title &downarrow;
def get(self, request, title):
blog = Blog.objects.filter(title=title)
return render(request,'blogs_read.html',{'blog':blog})
Here blog is a collection of zero, one, or more blogs. If you want to pass a single Blog object, you should fetch a single object, for example with get_object_or_404:
from django.shortcuts import get_object_or_404
class ReadBlogs(View):
def get(self, request, title):
blog = get_object_or_404(Blog, title=title)
return render(request,'blogs_read.html',{'blog':blog})
It might also make more sense to work with a DetailView [Django-doc] to automatically render the item properly:
from django.shortcuts import get_object_or_404
from django.views.generic.detail import DetailView
class ReadBlogs(DetailView):
model = Blog
template_name = 'blogs_read.html'
def get_object(self, *args, **kwargs):
return get_object_or_404(Blog, title=self.kwargs['title'])
template
{% url 'blogs:readblog' title=blogs.urltitle %}
here, you pass title=urltitle, so you actually pass urltitle!
views
# your-code | wrong
class ReadBlogs(View):
def get(self, request, title):
# ======== HERE, TITLE IS ACTUALLY urltitle! ==================
readblog = Blog.objects.filter(title=title)
return render(request,'blogs_read.html', {'readblog':readblog})
# correct
class ReadBlogs(View):
def get(self, request, title):
readblog = Blog.objects.filter(urltitle = title)
return render(request,'blogs_read.html', {'readblog':readblog})

Django: Including a form inside a listview

I am trying to insert a newsletter signup form into my base.html template which is a listview that displays upcoming events and featured shops and everytime I submit the form it returns a 'HTTP error 405'
Any help with this would be appreciated
Views.py
from django.shortcuts import render
from django.views.generic import ListView, TemplateView
from events.models import Event
from newsletter.forms import NewsletterSignUpForm
from shops.models import Shop
class HomeListView(ListView):
template_name = 'core/index.html'
def get_context_data(self, **kwargs):
context = super(HomeListView, self).get_context_data(**kwargs)
context.update({
'events': Event.get_upcoming_events()[:1], # returns only the first event in the list
'shops': Shop.objects.all(),
})
context['newsletter_form'] = NewsletterSignUpForm()
return context
def get_queryset(self):
return None
forms.py
from django.forms import ModelForm
from .models import Newsletter
class NewsletterSignUpForm(ModelForm):
class Meta:
model = Newsletter
fields = ['email']
Models.py
from django.db import models
class Newsletter(models.Model):
email = models.EmailField(unique=True)
date_subscribed = models.DateTimeField(auto_now=False, auto_now_add=True)
def __str__(self):
return f'{self.email}'
base.html
<form method="post">
{% csrf_token %}
{{ newsletter_form|crispy }}
<button class="btn btn-primary" type="submit">Sign Up!</button>
</form>
first add action url in form to handle post data
<form method="post" action="{% url 'submit_url' %}">
{% csrf_token %}
{{ newsletter_form|crispy }}
<button class="btn btn-primary" type="submit">Sign Up!</button>
</form>
urls.py
add url
path('your_url',views.formSubmit,name='submit_url')
views.py
def formSubmit(request):
if request.method == 'POST':
form = NewsletterSignUpForm(request.POST)
if form.is_valid():
form.save()
return redirect('your_list_view_url')
or you can use FormMixin along with classbased views
formmixin with classbased views

delete and modify comments by users

i've added to my Blog post comments now the problem is that i'm trying to create remove function for that and i have one but now eve uset thak is logged in can remove all the comments how can i fix this that user can delete only their own comments??
the funnyiest thing is that i have this function on my posts and it wokres and if i'm trying to do the same on my comments then i've get 404 error. Ive tried a few different ways but nothing worked You are my only hope:)
views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.contrib.auth.models import User
from .models import Post, Comment
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from .forms import CommentForm
from django.contrib.auth.decorators import login_required
# Create your views here.
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 5
class UserPostListView(ListView):
model = Post
template_name = 'blog/user_posts.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 5
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
class PostDetailView(DetailView):
model = Post
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = '/'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def about(request):
return render(request, 'blog/about.html', {'title': 'About'})
#login_required
def add_comment_to_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.post = post
comment.save()
return redirect('post-detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/add_comment_to_post.html', {'form': form})
#login_required
def comment_remove(request, pk):
comment = get_object_or_404(Comment, pk=pk)
comment.delete()
return redirect('post-detail', pk=comment.post.pk)
Models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=30)
text = models.TextField()
created_on = models.DateTimeField(default=timezone.now)
active = models.BooleanField(default=False)
class Meta:
ordering = ['-created_on']
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.text
post_detail
{% extends "blog/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{post.author.profile.image.url}}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user_posts' object.author.username %}">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted|date:"d F, Y" }}</small>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Update</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete</a>
</div>
{% endif %}
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
<hr>
<a class="btn btn-default" href="{% url 'add_comment_to_post' pk=post.pk %}">Add comment</a>
{% for comment in post.comments.all %}
{% if user.is_authenticated or comment.approved_comment %}
<div class="comment">
<div class="date">
<a class="btn btn-default" href="{% url 'comment_remove' pk=comment.pk %}">remove</a>
</div>
<strong>{{ comment.author }}</strong> {{ comment.created_on|date:"d F, Y G:i" }}
<p>{{ comment.text|linebreaks }}</p>
</div>
{% endif %}
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
{% endblock content %}
Firstly make author in Comment model Foreign Key(User). Then in views check this condition:
if comment.author == request.user:
comment.delete()

Django QuerySet filtering not working with views, showing blank view even though there are entries

I am attempting to view a particular set of objects with a certain attribute by using QuerySet filtering, however when I use the filter, the view returns blank. Not sure if I'm using this particular filter wrong, or if I'm calling on the attribute wrong, however I accessed other attributes (as seen below, the attribute "status") and found that it worked fine.
views.py:
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from .models import *
from .forms import *
#login_required
def vendorView(request):
return render(request, 'inv/vendorInventory.html')
#login_required
def consumerView(request):
return render(request, 'inv/consumerInventory.html')
def unauthenticatedView(request):
return render(request, 'inv/unauthenticatedInventory.html')
################ need to edit other views to render consumer/vendor/unauth
def display_drinks(request):
items = Drinks.objects.all()
context = {
'items': items,
'header': 'Drinks',
}
if not request.user.is_authenticated:
items = Drinks.objects.filter(status='AVAILABLE')
context = {
'items': items,
'header': 'Drinks',
}
return render(request, 'inv/unauthenticatedInventory.html', context)
elif request.user.profile.vendor:
items = Drinks.objects.filter(donatorID=request.user.username)
context = {
'items': items,
'header': 'Drinks',
}
return render(request, 'inv/vendorInventory.html', context)
elif not request.user.profile.vendor:
items = Drinks.objects.filter(status='AVAILABLE')
context = {
'items': items,
'header': 'Drinks',
}
return render(request, 'inv/consumerInventory.html', context)
inventory/models.py:
from django.db import models
from django.contrib.auth.models import User
from users.models import *
# Create your models here.
class Donation(models.Model):
description = models.CharField(max_length=200, blank=False, help_text='Describe your donation here')
choices = ( #for status
('AVAILABLE', 'Item ready to be picked up'),
('RESERVED', 'Item reserved'),
)
expiry = models.CharField(max_length=200, blank=False, help_text="Enter expiration date here")
status = models.CharField(max_length=10, choices=choices, default='AVAILABLE')
misc = models.CharField(max_length=50, blank=False, help_text='Miscellaneous info about your donation')
donatorID = models.CharField(max_length=50, default = User.username)
class Meta:
abstract = True
def __str__(self):
return '{0}'.format(self.description)
class Foods(Donation):
pass
class Drinks(Donation):
pass
class MiscObjects(Donation):
pass
As one can see, in models.py, the donatorID is assigned to the Donation object, and is the user's username. In the function display_drinks (in views.py), in the first elif, it should use the user's username to filter whatever items don't have the matching attribute, place items into a QuerySet that do match - however it displays blank, even though there are items that have matching attributes.
Would anyone know why this is occurring?
Thanks.
edit: as requested, here's vendorInventory.html:
{% extends "blog/base.html" %}
{% block body %}
<center> <div class="add_buttons">
<div class="btn-group-vertical">
View Food
Add Food
</div>
<div class="btn-group-vertical">
View Drinks
Add Drink
</div>
<div class="btn-group-vertical">
View Misc
Add Misc
</div>
</div>
</center>
<div>
<h4>Currently Viewing {{ header }}</h4>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>id</th>
<th>Description</th>
<th>Expiry Date</th>
<th>Status</th>
<th>Misc</th>
<th>Edit/Delete</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td>{{ item.pk }}
<td>{{ item.description }}</td>
<td>{{ item.expiry }} </td>
<td>{{ item.status }}</td>
<td>{{ item.misc }}</td>
{% if header|lower == "drinks" %}
<td>
<a href="{% url 'edit_drink' item.pk %}" class="btn btn-outline-info" role="button" aria-pressed="true" > Edit</a>
<a href="{% url 'delete_drink' item.pk%}" class="btn btn-danger btn-sm" role="button" aria-pressed="true" > x </a>
</td>
{% elif header|lower == "foods" %}
<td>
<a href="{% url 'edit_food' item.pk %}" class="btn btn-outline-info" role="button" aria-pressed="true" > Edit</a>
<a href="{% url 'delete_food' item.pk%}" class="btn btn-danger btn-sm" role="button" aria-pressed="true" > x </a>
</td>
{% else %}
<td>
<a href="{% url 'edit_miscObject' item.pk %}" class="btn btn-outline-info" role="button" aria-pressed="true" > Edit</a>
<a href="{% url 'delete_miscObject' item.pk%}" class="btn btn-danger btn-sm" role="button" aria-pressed="true" > x </a>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
forms.py:
from django import forms
from .models import *
class DrinkForm(forms.ModelForm):
class Meta:
model = Drinks
fields = ('description', 'expiry', 'status', 'misc', 'donator')
class FoodForm(forms.ModelForm):
class Meta:
model = Foods
fields = ('description', 'expiry', 'status', 'misc')
class MiscObjectForm(forms.ModelForm):
class Meta:
model = MiscObjects
fields = ('description', 'expiry', 'status', 'misc')
class ReserveDrinkForm(forms.ModelForm):
class Meta:
model = Drinks
fields = ('status',)
class ReserveFoodForm(forms.ModelForm):
class Meta:
model = Foods
fields = ('status',)
class ReserveMiscObjectForm(forms.ModelForm):
class Meta:
model = MiscObjects
fields = ('status',)
replace this in model
donatorID = models.ForeignKey(User, on_delete=models.CASCADE)
While saveing the data pass Users Object : variable_name = User.objects.get(username=request.user)
# models.py
from django.db import models
from users.models import *
# or if User model is not overwritten: from django.contrib.auth.models import User
class Donation(models.Model):
choices = ( # for status
('AVAILABLE', 'Item ready to be picked up'),
('RESERVED', 'Item reserved'),
)
description = models.CharField(max_length=200, help_text='Describe your donation here')
expiry = models.CharField(max_length=200, help_text="Enter expiration date here")
status = models.CharField(max_length=10, choices=choices, default='AVAILABLE')
misc = models.CharField(max_length=50, help_text='Miscellaneous info about your donation')
donator = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
abstract = True
def __str__(self):
return self.description
class Foods(Donation):
pass
class Drinks(Donation):
pass
class MiscObjects(Donation):
pass
# views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from users.models import *
# or if User model is not overwritten: from django.contrib.auth.models import User
from .models import *
from .forms import *
#login_required
def vendorView(request):
return render(request, 'inv/vendorInventory.html')
#login_required
def consumerView(request):
return render(request, 'inv/consumerInventory.html')
def unauthenticatedView(request):
return render(request, 'inv/unauthenticatedInventory.html')
################ need to edit other views to render consumer/vendor/unauth
def display_drinks(request):
items = Drinks.objects.all()
context = {
'items': items,
'header': 'Drinks',
}
if not request.user.is_authenticated:
items = Drinks.objects.filter(status='AVAILABLE')
context = {
'items': items,
'header': 'Drinks',
}
return render(request, 'inv/unauthenticatedInventory.html', context)
elif request.user.profile.vendor:
items = Drinks.objects.filter(donator__username=request.user.username)
context = {
'items': items,
'header': 'Drinks',
}
return render(request, 'inv/vendorInventory.html', context)
elif not request.user.profile.vendor:
items = Drinks.objects.filter(status='AVAILABLE')
context = {
'items': items,
'header': 'Drinks',
}
return render(request, 'inv/consumerInventory.html', context)
This will work, BUT better to use class-based views here for example:
official documentation: https://docs.djangoproject.com/en/dev/topics/class-based-views/
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
from django.views.generic.list import ListView
# Better naming for model will be a "Drink" instead of "Drinks" (Django code style)
from .models import Drinks
class VendorView(LoginRequiredMixin, TemplateView):
# better to use 'inv/vendor_inventory.html' naming style for PEP8 compatibility.
template_name = 'inv/vendorInventory.html'
class ConsumerView(LoginRequiredMixin, TemplateView):
template_name = 'inv/consumerInventory.html'
# Name for view, I think looks terrible ;)
class UnauthenticatedView(TemplateView):
template_name = 'inv/unauthenticatedInventory.html'
class DrinksListView(ListView):
model = Drinks
context_object_name = 'items' # Variable in template, better to use something like: context_object_name = 'drinks'
def get_queryset(self):
if self.request.user.is_authenticated():
return Drinks.objects.filter(status='AVAILABLE')
elif self.request.user.profile.vendor:
return Drinks.objects.filter(donator__username=self.request.user.username)
# Better to use "else:" here instead of "elif" (for all other logic).
elif not self.request.user.profile.vendor:
return Drinks.objects.filter(status='AVAILABLE')
Answers for questions from comments:
If you want to add automatically user for every new Drinks object, you should do something like this:
First of all, you should exclude field "donator" in your form:
# forms.py
class MyForm(forms.ModelForm):
#.....
class Meta:
model = Drinks
exclude = ('donator', )
If you use function-based views:
you should add something like this:
# views.py
if request.GET:
form = MyForm()
if request.POST:
form = MyForm(request.POST)
if form.is_valid():
drinks = form.save(commit=False)
drinks.donator = request.user
drinks.save()
return render(request, 'my_temlate.html', {'form': form})
If you use class-based views: you should overwrite "post" method same way. You can find out more here, also there are examples: How do I use CreateView with a ModelForm

Cannot POST correctly when submitting form in Django

I am trying to upload files (specifically images) to a database. When I try to POST my form in profile_photo.html (attached below), it gives me an error saying:
MultiValueDictKeyError at /user_profile/login/upload_profile_photo/
profile_photo.html:
<body>
<div id="blue_background_with_fibers">
<form class="pull-center white form-signin" role="form" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %} {{ form.as_p }}
<button class="aqua button2" type="submit" value="OK">Upload</button>
</form>
</div>
detail.html that uses profile_photo.html:
<div class="modal fade" id="profile" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Upload Profile Picture</h4>
</div>
<div class="modal-body">
<form>
<!--Insert form here-->
<iframe src="upload_profile_photo/" allowTransparency="true" scrolling="yes" frameborder="0" width="560px" height="175px"></iframe>
</form>
</div>
<div class="modal-footer">
<span>Ekho © 2016</span>
</div>
</div>
</div>
</div>
I believe that I am messing up in my views.py (specifically under the EditProfileView class). Below is my views.py:
class EditProfileView(View):
form_class = EditProfileForm
def get(self, request):
form = self.form_class(None);
return render(request, 'ekho/profile_photo.html', {'form': form})
def post(self, request):
if not request.user.is_authenticated():
return render(request, 'ekho/login.html')
else:
form = EditProfileForm(request.POST or None, request.FILES or None)
if form.is_valid():
user = form.save(commit=False)
user.user = request.user
user.profile_photo = request.FILES['profile_photo']
file_type = user.profile_photo.url.split('.')[-1]
file_type = file_type.lower()
if file_type not in IMAGE_FILE_TYPES:
context = {
'user': user,
'form': form,
'error_message': 'Image file must be PNG, JPG, or JPEG',
}
return render(request, 'ekho/detail.html', context)
user.save()
return render(request, 'ekho/login.html', {'user': user})
return render(request, 'ekho/detail.html', {"form": form,})
Models.py:
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile');
background = models.FileField(upload_to = 'user_profile/media/', blank=True, null=True);
profile = models.FileField(upload_to = 'user_profile/media/', blank=True, null=True);
about = models.TextField(default='', blank=True);
reviews = models.TextField(default='', blank=True);
def __str__(self):
return self.user.username
And finally urls.py:
from django.conf.urls import url
from . import views
app_name = 'user_profile'
urlpatterns = [
# /user_profile/
url(r'^$', views.index, name='index'),
# /user_profile/username
url(r'^user_profile/detail/$', views.detail, name='detail'),
# user_profile/register/
url(r'^register/$', views.RegisterFormView.as_view(), name='register'),
# user_profile/login/
url(r'^login/$', views.LoginFormView.as_view(), name='login'),
url(r'^login/upload_profile_photo/$', views.EditProfileView.as_view(), name='edit_profile')
]
This but be the problem
In your views.py file you are trying to access 'profile_photo' which should have been in 'profile' according to your models.py
views.py
user.profile_photo = request.FILES['profile_photo']
This error MultiValueDictKeyError occurs when you try to access the key that is not available in Dict
I guess this should work
views.py
user.profile_photo = request.FILES['profile']
PyMentor has a grate tutorial to post form with image in django.
http://pymentor.in/upload-image-file-using-django/
For your second problem: UNIQUE constraint failed: user_profile_userprofile.user_id
You can't use form.save to retrieve the UserProfile instance. It will create another user profile object after calling form.save, so you will get UNIQUE constraint error.
Try to replace form.save with:
user = User.objects.get(pk=request.user.pk).profile