I'm a bit stumped. So I have two models, as shown in models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
activation_key = models.CharField(max_length=40, blank=True)
key_expires = models.DateTimeField(default=datetime.date.today())
def __str__(self):
return self.user.username
class Meta:
verbose_name_plural='User profiles'
class ImageDoc(models.Model):
user = models.ForeignKey(UserProfile)
imgfile = models.ImageField(upload_to='images/')
It's a simple profile function, and what I'm trying to do is display images related only to the user after they log in.
Here's my views.py file:
def sign_in(request):
context = RequestContext(request)
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/', context)
else:
return HttpResponse("Verify your account!")
else:
return HttpResponse("Invalid login details supplied.")
def populateContext(request, context):
context['authenticated'] = request.user.is_authenticated()
if context['authenticated'] == True:
context['username'] = request.user.username
def index(request):
context = {}
populateContext(request, context)
context.update(image_gallery = ImageDoc.objects.only('imgfile'))
return render(request, 'index.html', context)
In the index.html page, I can display the user who has logged in, thanks to populateContext above. This includes these:
{{ request.user.first_name }} {{ request.user.last_name }} {{ request.user.username }} {{ request.user.email }} {{ request.user.id }}
However, I don't know how to display "imgfile" from the related model. It works if I do this:
{% for x in image_gallery %}
<img src="{{ x.imgfile }}">
{% endfor %}
But only because I updated the context above to include it in. Ideally I want the image to display just on a particular user's page. Exactly like a member gallery. Thank you in advance for any help.
You can write a simple method for UserProfile model, that will return all images related to current user:
class UserProfile(models.Model):
# some stuff here
def get_images(self):
return ImageDoc.objects.filter(user=self)
Now you can access images in a template:
{% for image in user.userprofile.get_images %}
<img src="{{ image.imgfile }}">
{% endfor %}
Related
I want to get the total number of tables own by each users on my application. using Tables.objects.all().count returns all total number of tables but I will like to get the number of tables own by each user.
models.py
class User(AbstractBaseUser, PermissionsMixin):
name = models.CharField(max_length=30, blank=True, null=True)
class Bar(models.Model):
user_id = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
class Tables(models.Model):
table_no = models.CharField(max_length=14, unique=False)
bar = models.ForeignKey(to=Bar, on_delete=models.CASCADE)
views.py
def Dashboard(request, pk):
user = User.objects.get(pk=pk)
reservations = Tables.objects.filter(bar__user_id=user)
pending = Reservation.objects.filter(status="pending")
confirmed = Reservation.objects.filter(status="confirmed")
context = {"reservations":reservations, "pending":pending, "confirmed":confirmed}
return render(request, "dashboard/super/landlord/dashboard.html", context)
class Login(View):
""" Login View."""
form_class = LoginForm
template_name = "dashboard/auth/login.html"
def get(self, request):
logout(request)
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
Email = form.cleaned_data.get('Email')
password = form.cleaned_data.get('password')
user = authenticate(username=Email, password=password)
messages.success(request, "you have logged in successfully ")
if user is not None:
if user.is_active:
login(request, user)
return redirect('/dashboard')
else:
error = "Email or password is incorrect"
return render(
request, self.template_name, {'form': form, 'error': error})
urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('dashboard/<int:pk>/', Dashboard, name="dashboard"),
]
templates.html
<li {% if request.path == '/dashboard/' %} class="active" {% endif %}><i class="ion-home"></i> <span class="nav-label">Dashboard</span>
</li>
Michael Lindsay pretty much answered your question here, only query the user you need, for example if this was a view:
def all_user_tables(request, pk):
user = User.objects.get(pk=pk)
tables = Tables.objcets.filter(bar__user_id=user)
tables_count = tables.count()
return render(request, 'all_user_tables.html', {'user': user,
'tables': tables,
'tables_count': tables_count})
then in your template:
{% extends 'base.html' %}
{% block content %}
<p>Tables for user {{ user }}</p>
{% for table in tables %}
{{ table }}
{% endfor %}
<p>Total {{ table_count }} tables.</p>
{% endblock %}
Double underscores allows filter() to follow ForeignKey relations
user = User.objects.get(email="nasir#yahoo.com")
tbl_count = Tables.objects.filter(bar__user_id=user).count()
So I want to let a user message another user. I want the 'sender' field automatically to be 'request.user' and the receiver field to be the user whom the sender clicked on through their profile page. How would I go about passing those into the form?
matches.html
<div class="container">
<p>Username: {{ profile }}</p>
<h5>Your Matches:</h5>
{% for item in match %}
<br>
<p>Username: <br>{{ item.username}}</p>
<img src="{{ item.photo.url }}" width="300">
<p>Bio: <br>{{ item.description }}</p>
<br>
{% endfor %}
</div>
forms.py/InstantMessageForm
class InstantMessageForm(forms.ModelForm):
class Meta:
model = InstantMessage
fields = ('receiver','sender','message')
def save(self, commit=True):
user = super(InstantMessageForm, self).save(commit=False)
user.receiver = cleaned_data['receiver']
user.sender = cleaned_data['sender']
user.message = cleaned_data['message']
if commit:
user.save()
return user
views.py/instant_message
def instant_message(request):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
models.py
class InstantMessage(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
message = models.TextField()
class InstantMessage(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
message = models.TextField()
instant_message_form.py
{% extends "dating_app/base.html" %}
{% load bootstrap4 %}
{% block content %}
<h1>Start chatting now!</h1>
<div class='container'>
<form method="post" action="{% url 'dating_app:instant_message' %}" >
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
</div>
{% endblock content %}
You can create a form without the sender field:
class InstantMessageForm(forms.ModelForm):
class Meta:
model = InstantMessage
fields = ('receiver', 'message')
Then in the view, you can inject the request.user as the .sender of .instance wrapped in the form:
from django.contrib.auth.decorators import login_required
#login_required
def instant_message(request):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.instance.sender = request.user
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
In order to set the receiver, your url should for example contain the a primary key of the receiver. You can then remove the receiver from the form as well, and thus use:
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
#login_required
def instant_message(request, receiver_id):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.instance.sender = request.user
form.instance.receiver = get_object_or_404(get_user_mode(), pk=receiver_id)
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
You of course need then to alter the urls.py accordingly and the action url, such that it includes the primary key of the receiver.
I have a registration form and am adding a user profile to add another field.
after the registration form is filled and submitted the form details are not submitted
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Assigned_Group = models.CharField(max_length=500)
def __str__(self):
return self.user.username
views.py
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
profile_form = UserProfileForm(request.POST)
if form.is_valid() and profile_form.is_valid():
user = form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('index')
else:
form = RegistrationForm()
profile_form = UserProfileForm()
context = {'form': form, 'profile_form':profile_form}
return render(request, 'registration/register.html', context )
def index(request):
if request.user.is_authenticated:
username = request.user.username
else:
username = 'not logged in'
context = {'username':username}
return render(request, 'index.html', context)
urls.py
path('Register/', views.register, name='register'),
in your html page in body you have to insert {% csrf_token %} like:
<html>
<body>
{% csrf_token %}
</body>
Inside your html form you will need to have inserted {% csrf_token %}.
See the django docs on CSRF for more information or if you are using AJAX.
For example your html will then look something like.
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
Side note from the django docs (which is important).
In the corresponding view functions, ensure that RequestContext is used to render the response so that {% csrf_token %} will work properly. If you’re using the render() function, generic views, or contrib apps, you are covered already since these all use RequestContext.
I'm trying to create an edit form for existing users, I have the User model and I associated to it a profile.
The problem is that the fields of profile are empty in the rendered html, however when I created a new user I filled these fields, and when I enter to administration I find the fields are filled.
models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
DEPARTMENT_CHOICES = (('MI', 'Math et info'),
('ST', 'Science et Tech'),
('SM', 'Science de la matiere'))
user = models.OneToOneField(User, on_delete=models.CASCADE)
teacher = models.BooleanField(default=False)
description = models.TextField(blank=True)
department = models.CharField(max_length=35, choices=DEPARTMENT_CHOICES, blank=True)
picture = models.ImageField(upload_to='profile-images', blank=True)
def __str__(self):
return self.user.username
views.py
def profile_view(request):
if request.method == 'POST':
user_form = EditUserForm(request.POST, instance=request.user)
ins = Profile.objects.get(pk=5)
profile_form = EditProfileForm(request.POST, request.FILES, instance=ins)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
profile.save()
return redirect(home)
else:
user_form = EditUserForm(instance=request.user)
profile_form = EditProfileForm(request.FILES, instance=request.user)
return render(request, 'account/profile.html', {'user_form': user_form,
'profile_form': profile_form})
forms.py
class EditProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('description', 'department', 'picture', )
class EditUserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email', )
profile.html
{% extends 'manhal/base.html' %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block content %}
<div class="col-md-6">
<form method="post" enctype="multipart/form-data" action="{% url 'profile' %}" class="form-horizontal">{% csrf_token %}
<fieldset>
<legend>User Profile</legend>
{{ user_form|crispy }}
{{ profile_form|crispy}}
<input type="submit" value="Save" class="btn btn-primary">
</fieldset>
</form>
</div>
{% endblock %}
First, your if/else block is checking if the request is a POST. Since the else block is not a POST, you do not want to pass any POST data into your form. This will make the form think it's bound with no data.
Also, it looks like you are passing the request.user to your ProfileForm as the instance, but the model on the ProfileForm meta class is expecting a Profile object.
Can you fix those two things and see if it works or not? If it doesn't work, please post some more code (like your templates).
Okay so it appears I'm in way over my head on this small task. I'd like to ask how exactly does one submit to a form, without relying on the URL values?
In my example, the user has to log in before they can see their gallery pictures. Determining this is via "context", which has the active user (as logged in) assigned to it. Props to #chem1st & #Daniel-Roseman for the assistance earlier in helping me figure that out yesterday. Now it can display their own user gallery in the homepage after they log in.
I prefer not uploading with "blahblah.com/bobby/upload", because it doesn't seem very secure. I'd like to let logged in users upload via "blahblah.com/upload/". Which means the form in the view.py would have to get the context of the user who's logged in, somehow, and save the data to the database under that account.
I've been toying around, and searching for answers, but can't find anything. Can someone help point me in the right direction?
Here's my models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
activation_key = models.CharField(max_length=40, blank=True)
key_expires = models.DateTimeField(default=datetime.date.today())
def __str__(self):
return self.user.username
class Meta:
verbose_name_plural='User profiles'
class ImageDoc(models.Model):
user = models.ForeignKey(UserProfile)
imgfile = models.ImageField(upload_to='images/')
forms.py:
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'placeholder': 'E-mail address'}))
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'username', 'password1', 'password2')
class ImgDocForm(forms.Form):
user_file = forms.ImageField()
def clean_user_file(self, *args, **kwargs):
cleaned_data = super(ImgDocForm,self).clean()
user_file = cleaned_data.get("user_file")
if user_file:
if user_file.size > 5 * 1024 * 1024:
raise forms.ValidationError("Filesize is too big.")
if not os.path.splitext(user_file.name)[1].strip().lower() in ['.jpg','.png','.gif','.jpeg']:
raise forms.ValidationError("File does not look like as picture.")
return user_file
class UserForm(forms.Form):
class Meta:
model = User
fields = ['first_name', 'last_name', 'password', 'email', 'username']
My views.py file (EDIT: Changed the Index to display the user details, the gallery, and a quick upload function):
def sign_in(request):
context = RequestContext(request)
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/', context)
else:
return HttpResponse("Verify your account!")
else:
return HttpResponse("Invalid login details supplied.")
def populateContext(request, context):
context['authenticated'] = request.user.is_authenticated()
if context['authenticated'] == True:
context['username'] = request.user.username
def index(request):
user_details = UserProfile.objects.get(user=request.user)
gallery = ImageDoc.objects.filter(user_id=request.user.id)
if request.method == 'POST':
form = ImgDocForm(request.POST, request.FILES)
if form.is_valid():
origin_form = form.cleaned_data["user_file"]
origin_name = origin_form.name
original_name = ImageDoc(user_id=request.user.id, imgfile=origin_name)
original_name.save()
return HttpResponse('Saved!')
else:
form = ImgDocForm()
documents = ImageDoc.objects.all()
return render(request, 'test.html', {'documents': documents, 'form': form, 'user_details': user_details, 'gallery': gallery})
def upload(request):
data = {}
thumb_size = (100,100)
micro_thumb_size = (50,50)
if request.method == 'POST':
userform = ImgDocForm(request.POST, request.FILES)
if userform.is_valid():
origin_form = userform.cleaned_data["user_file"]
origin_name = origin_form.name
original_file = os.path.join(settings.MEDIA_ROOT, origin_name)
.
.
.
original_name = ImageDoc(imgfile=origin_name)
original_name.save()
.
.
.
userform = ImgDocForm()
else:
return HttpResponse('Nooo!')
else:
userform = ImgDocForm()
data.update(image_gallery = ImageDoc.objects.only('imgfile'))
data.update(userform=userform)
data.update(csrf(request))
return render(request, 'upload.html', data)
EDIT: I'm sure folks can clean up the index file significantly. Also, not very elegant at the bottom there, but it works.
And the upload.html document:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div>
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ userform.as_p }}
<input type="submit">
</form>
<br><br>
<h2>{{ origin_name }} (original)</h2>
{% if origin_name %}
<img src="{{ MEDIA_URL }}{{ origin_name }}">
{% endif %}
<br><br>
{% if image_gallery %}
{% for image in image_gallery %}
<img src="/{{ image.thumbfile }}">
{% endfor %}
{% endif %}
</div>
</body>
</html>
Thank you!
You can get currently logged in user inside the view as request.user.