Hyperlinks in Django for loop are linking to the same page - python

On a user's profile page right now it is displaying the number of people they are following and the usernames of the people they are following. When the user clicks on a username, I quite simply want it to take the user to that user's profile page but right now it is linking back to the same user's profile page, so essentially just reloading the page.
I am guessing it is because I am passing in user.username as a keyword argument because when I follow this same format but instead using user.id I don't run into this problem. I would like to use user.username so that the username can be displayed in the url.
rofilePage.html
{% block body %}
<h3>{{ user.username }}</h3>
<br>
<br>
<p>{{ profile.number_of_friends }}</p>
<p>{% for friend in profile.get_friends %}</p>
{{ friend }}<br>
{% endfor %}
{% endblock %}
views.py:
def profile_page(request, user_username):
profile = get_object_or_404(Profile, user__username=user_username)
return render(request, "network/profilePage.html", {
"profile": profile
})
urls.py:
path("profile/<str:user_username>", views.profile_page, name="profile"),
models.py:
class User(AbstractUser):
pass
class Profile(models.Model):
user = models.OneToOneField("User", on_delete=models.CASCADE, primary_key=True)
friends = models.ManyToManyField("User", related_name='following', blank=True, symmetrical=False)

<p>{% for friend in profile.get_friends %}</p>
{{ friend }}<br>
{% endfor %}
You are iterating over friends but not mentioning it, should be {{ friend }}<br>

{% for friend in profile.get_friends %}
is there a problem??
you are putting for in <p> tag?
try this:
{% for friend in profile.get_friends %}
<p>
{{ friend }}<br>
</p>
{% endfor %}

Related

How to use Customize Model extends from User Model in Django?

I'm new to Django and I have a problem that makes me quite confused. I have a page when users click to change profile, the corresponding page shows up and lets users update their profile. Here is my model:
from django.db import models
import os
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.utils import timezone
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class Account(models.Model):
user = models.ForeignKey(User, on_delete="CASCADE")
phone = models.CharField(max_length=18)
room = models.CharField(max_length=8)
dob = models.DateField(default=timezone.datetime.now())
active = models.BooleanField(default=True)
avatar = models.ImageField(upload_to='images/', default=os.path.join(settings.STATIC_ROOT, 'avatar.png'))
def __str__(self):
return self.user.username
Here are my forms:
class UserForm(forms.ModelForm):
first_name = forms.CharField(max_length=100,
widget=forms.TextInput(attrs={'class': 'uk-input', 'placeholder': 'Last Name'}))
last_name = forms.CharField(max_length=100,
widget=forms.TextInput(attrs={'class': 'uk-input', 'placeholder': 'Last Name'}))
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
class ProfileForm(forms.ModelForm):
class Meta:
model = Account
fields = ['phone', 'room', 'dob', 'active', 'avatar']
And I have my views.py like this:
def show_form(request):
user_basic_info = UserForm(request.POST)
form = ProfileForm(request.POST)
if form.is_valid() and user_basic_info.is_valid():
form.save() and user_basic_info.save()
messages.sucess(request, _('Your profile has been successfully updated'))
redirect('my_account')
else:
UserForm()
ProfileForm()
context = {
'user_basic_info': user_basic_info,
'form': form,
}
return render(request, 'my_account.html', context)
Here is my_account.html template:
{% extends 'base.html' %}
{% block title %}My account{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item active">Update your information</li>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-6 col-md-8 col-sm-10">
<form method="post" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Save changes</button>
</form>
</div>
</div>
{% endblock %}
And forms.html:
{% load widget_tweaks %}
<table>
<div class="form-group">############
{{ user_basic_info }} ############# This displays first_name, last_name and email. Also the problem's here, I want to make 2 forms in one form with a better style like the form below.
</div>############
</table>
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
<p{% if forloop.last %} class="mb-0"{% endif %}>{{ error }}</p>
{% endfor %}
</div>
{% endif %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }} {% if form.is_bound %} {% if field.errors %} {% render_field field class="form-control is-invalid" %} {% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %} {% else %} {% render_field field class="form-control is-valid" %} {% endif %} {% else %} {% render_field field class="form-control" %} {% endif %} {% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text|safe }}
</small> {% endif %}
</div>
{% endfor %}
So when users want to change their profile, those fields first_name, last_name, email, phone, room, dob, active, avatar need to be displayed. But the first 3 fields belong to the User model and the rest fields are defined in my Account model. I want when users submit the form, those fields are linked together, e.g Account is an instance of User and that information is properly saved to the database in Account model (I have watched some tutorials but I still cannot properly do it). And when logging to the page, login authentication using User model, but when updating the profile it's Account model and User model, but there is no relationship between them, how can I fix all of those errors, thanks in advance.
you need to use OneToOne Relationship here since each user has only one and unique profile details. so in your models.py use :-
user = models.OneToOneField(User, on_delete=models.CASCADE)
If you use default user there is 4 way to extends it so here i give a link follow them,
if you use default user you need to use Usercreation form for Register because the user model have password encryption algorithmuse so when you use you user define form it will not store your password
follow instruction for extends user abstract base model
extends user using
registration form using usercreation form
Define view of save data
follow instruction for extends user using one to one
Create new model Profile and give one to one relationship
Create registration form usring model.formplus additional fields you want to take from user define in form class explicity
in view save form and add user reference in Profile model using create method
link:
extend user model
if you use usercreation form
go through i give link if you got error let me know

ForeignKey don't show data

When I try to use foreignKey, html don't response
Models.py
class Home(models.Model):
book = models.ForeignKey(Book, verbose_name=(
"book"), on_delete=models.CASCADE, related_name="book")
Views.py
def main(request):
posts = Home.objects.all()
return render(request, 'home/home-page.html', {'posts': posts})
HTML
{% for post in posts %}
{% for book in post.book.all %}
{{ book }}
{% endfor %}
{% endfor %}
What going wrong?
all doesn't make any sense here, with a one to many relationship home only has one book, a book has many homes
so the inner for loop isn't needed, you can just use post.book
{% for post in posts %}
{{ post.book }}
{% endfor %}

How to display user name and surname in main page after Django login

Instead of the user, I want to display the user name and surname in the main page, after the log in. But my user model is extended by another form which holds the name and surname fields.
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}
This will display the user name. But my second form has a OnetoOneField with the User model. I tried something like user.form2.name but it's not a solution.
{% if request.user.is_authenticated %}
<p>Welcome, {{ request.user.<name_of_one_to_one_model_in_lower_case>.surname }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}

Can't list all user emails in Django

I am trying to show a list of user emails in my user profile template, which seems like a really simple thing to do, but I can't get anything to display.
I've tried using {{ email }} in my loop, but it just returns the current users email a bunch of times.
I've also used {{ emailAddress.email }} which doesn't return anything.
My user profile template:
{% extends "base.html" %}
{% block content %}
<title>{% block title %} | {{ username }}{% endblock %}</title>
<h2>{{ username }}</h2>
<p><b>Location: </b>{{ user.profile.location }}</p>
<p><b>Email: </b>{{ email }}</p>
<p>
{% for emailAddress in emailList %}
{{ user.email }}
{% endfor %}
</p>
Edit Profile
{% endblock content %}
My user profile view:
def loggedin(request):
return render_to_response('loggedin.html',
{'username':request.user.username,
'user':request.user, 'email':request.user.email,
'emailList':User.objects.values_list('email', flat=True)})
Something's wrong with your for loop.
{% for emailAddress in emailList %}
{{ user.email }}
{% endfor %}
You are looping through emailList and every element is assigned to a variable emailAddress. Your loop should look like this.
{% for emailAddress in emailList %}
{{ emailAddres }}
{% endfor %}
Note that emailList is already a list of emails so you don't need to do emailList.email.

Django - Retrieve Data for 2 Separate Querysets On One Page

I am using Django, PyCharm 2018.3.7, Python 3.7, and Postgres.
Unfortunately, I do not understand how to display on one screenpage (Django form) the results for 2 separate querysets that need the same ID passed by a dynamic filter request (GET). There is a table/model (ASSIGNMENTS) with a One-To-Many relationship to another table/model (PRODUCTS). The ID being passed is the ASSIGNMENTS.ID, which is the PK of ASSIGNMENTS and the FK of PRODUCTS.
I am not trying to join these 2 querysets. I need the user to see the information for the ASSIGNMENT first and then below I want them to see all of the PRODUCTS that belong to that ASSIGNMENT.
I do not need to update/create data, so no POST is needed. Only want to retrieve, GET, data that exists.
Below are the code for models.py, views.py, and templates. It works perfect with just ASSIGNMENTS.
MODELS.PY
class Assignments(models.Model):
id = models.DecimalField(db_column='ID', primary_key=True, max_digits=9, decimal_places=0)
name = models.CharField(db_column='NAME', unique=True, max_length=40)
def __str__(self):
return self.name + ' ' + '(' + '#' + str(self.id) + ')'
class Meta:
ordering = 'name',
db_table = 'ASSIGNMENTS'
class Products(models.Model):
id = models.DecimalField(db_column='ID', primary_key=True, max_digits=11, decimal_places=0)
assignment = models.ForeignKey(Assignments, models.DO_NOTHING, related_name='productsfor_assignment', db_column='ASSIGNMENT_ID', blank=True, null=True)
name = models.CharField(db_column='NAME', max_length=80)
def __str__(self):
return self.name + ' ' + '(' + '#' + str(self.id) + ')'
class Meta:
ordering = 'name',
db_table = 'PRODUCTS'
VIEWS.PY
def search_form(request):
return render(request, 'assignments/search_form.html')
def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
assign = Assignments.objects.filter(id__icontains=q)
return render(request, 'assignments/search_results.html',
{'AssignmentsResults': assign, 'query': q})
else:
# if the query is empty, render the 'search_form html' template again.
# display an error message in that template. So, pass a template variable.
# 'search_form html' will check for the 'error' variable
return render(request, 'assignments/search_form.html', {'error': True})
TEMPLATE 'search_form.html'
{% extends "base.html" %}
{% block content %}
<br><br>
<h1> Assignment ID Search Form </h1>
<br><br>
{% if error %}
<p style="color: red;">Please submit a search term.</p>
{% endif %}
<form action="/search/" method="get">
<input type="text" name="q" placeholder="Enter ID here ...">
<input type="submit" value="Search">
</form>
<p>
Page last updated: {{ last_updated|date:'D d F Y' }}
</p>
{% endblock content %}
TEMPLATE 'search_results.html'
{% extends "base.html" %}
{% block content %}
<br><br>
<h1> Assignment ID Search Results</h1>
<p>You searched for: <strong>{{ query }}</strong></p>
{% if AssignmentsResults %}
<ul>
{% for assignments in AssignmentsResults %}
<li>
{{ assignments.id }}, {{ assignments.name }}
</li>
{% endfor %}
</ul>
{% else %}
<p>No assignments matched your search criteria.</p>
{% endif %}
{% endblock content %}
This is what I finally put together to include Products (shown below in the failed views.py and template). But, it does not work.
This was the FAILED VIEWS.PY
def search_form(request):
return render(request, 'assignments/search_form.html')
def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
assign = Assignments.objects.filter(id__icontains=q)
prod = Products.objects.filter(assignment__icontains=q)
return render(request, 'assignments/search_results.html',
{'AssignmentsResults': assign, 'query': q})
return render(request, 'assignments/search_results.html',
'ProductsResults': prod, 'query': q)
else:
# if the query is empty, render the 'search_form html' template again.
# display an error message in that template. So, pass a template variable.
# 'search_form html' will check for the 'error' variable
return render(request, 'assignments/search_form.html', {'error': True})
This was the FAILED TEMPLATE CODE 'search_results.html
{% extends "base.html" %}
{% block content %}
<br><br>
<h1> Assignment ID Search Results</h1>
<p>You searched for: <strong>{{ query }}</strong></p>
{% if AssignmentsResults %}
<ul>
{% for assignments in AssignmentsResults %}
<li>
{{ assignments.id }}, {{ assignments.name }}
</li>
{% endfor %}
</ul>
<p> These are the Products attached to the Assignment.</p>
{% if ProductsResults %}
<ul>
{% for products in ProductsResults %}
<li>
{{ products.assignment }}, {{ products.name }}
</li>
{% endfor %}
</ul>
{% else %}
<p> No products for this assignment exist.</p>
{% endif %}
{% else %}
<p>No assignments matched your search criteria.</p>
{% endif %}
{% endblock content %}
I have created the project by following 'Build a website with Django 2, updated for Django 2.2' by Nigel George. I have looked at several youtube instructional videos and read questions on stackoverflow. (These are only a couple.)
How to combine two or more querysets in a Django view?
Displaying a series of inline forms for a queryset of Django models
Django: Add queryset to inlineformsets
Django nested QuerySets
InlineFormSet with queryset of different model
However, none of them have been able to help me with my problem of presenting 2 separate queryset results on one form.
I'd certainly appreciate any suggestions and help provided.
Thanks
Okay, let's see. If you just want to display the information that it seems to be intended in search_results.html, I suggest you to refactor a little bit your query as follows.
(I will try to clean out the weird things (for example having two consecutive return statements) as much as I can to illustrate my point)
views.py:
from django.shortcuts import render, redirect
from django.urls import reverse
def search(request):
q = request.GET.get('q', None)
if q:
assignments_qs = Assignments.objects.filter(id__icontains=q) \
.prefetch_related('productsfor_assignment')
context_data = {'assignments': assignments_qs}
return render(request, 'assignments/search_results.html', context_data)
else:
return redirect(reverse('search_form', kwargs={'error': True}))
def search_form(request, error=False):
return render(request, 'assignments/search_form.html', {'error': error})
search_results.html
{% if assignments %}
<ul>
{% for assignment in assignments %}
<li>
{{ assignment.id }}, {{ assignment.name }}
</li>
{% if assignment.productsfor_assignment.exists %}
<p> These are the Products attached to the Assignment.</p>
<ul>
{% for product in assignment.productsfor_assignment.all %}
<li>
{{ product.assignment }}, {{ product.name }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No assignments matched your search criteria.</p>
{% endif %}
I think this is the best and the most similar way to achieve what you want considering what you currently have.

Categories