Problems with passing data from view to template? - python

I am new to Django Python and I am learning how to use Django and passing data from view to template. Now, here is my situation and I really need some help in understanding where i can be doing wrong.
I am trying to pass data from view to template and then parse the object in the view but for some reason nothing is happening in the template. I have printed the registration object in my views.py and it works fine and displays the information that is correct. But when I send the registration object from views to template nothing happens.
models.py
from django.db import models
from datetime import datetime
from django.shortcuts import redirect
# Create your models here.
# Create your models here.
class Registration(models.Model):
first_name = models.CharField(max_length=255, null=True, blank=True)
last_name = models.CharField(max_length=255, null=True, blank=True)
email = models.CharField(max_length=255, null=True, blank=True)
password = models.CharField(max_length=255, null=True, blank=True)
mobilenumber = models.CharField(max_length=255, null=True, blank=True)
created_on = models.DateTimeField(auto_now_add=True, blank=True)
class Meta:
ordering = ('first_name',)
views.py
class Loginview(CreateView):
model = Registration
form_class = LoginForm
template_name = "loginvalentis/valentis_login.html"
def get(self, request):
form = LoginForm()
# returning form
return render(request, 'loginvalentis/valentis_login.html', {'form': form});
def form_valid(self,form):
user_email = form.cleaned_data.get('email')
user_password = form.cleaned_data.get('password')
try:
registration = Registration.objects.get(email=user_email)
print ("registration",registration.mobilenumber)
return redirect('/loginvalentis/home/',{'registration':registration})
except Registration.DoesNotExist:
user_info = None
return redirect('/loginvalentis/login/')
Template result.html --- ('/loginvalentis/home/')
<html>
<body>
<form id="form1">
{% csrf_token %}
<div>
hello world
<form id ="form1">
<ul>
{% for user in registration %}
<li>{{ user.mobilenumber }}</li>
{% endfor %}
</ul>
</form>
</div>
</form>
</body>
</html>

Your problem is with the redirect() function. You are trying to pass the registration object through it, but it doesn't support this, it's *args and **kwargs are simply a parameters for reversing the url, see here:
https://docs.djangoproject.com/en/2.0/topics/http/shortcuts/#django.shortcuts.redirect
You should use some other way to pass it to another view, e.g. pass only it's id as a parameter of that view's url (you will have to change the url conf appropriatelly), the other way is to use sessions etc.
see:
https://docs.djangoproject.com/en/2.0/topics/http/sessions/
https://docs.djangoproject.com/en/2.0/topics/http/urls/
But really, it would be much easier for you just to walk through this tutorial very carefully
https://docs.djangoproject.com/en/2.0/intro/tutorial01/ trust me, it will be really worth your time, because from your question I can easily tell that you just don't understand what you are doing.

Related

How to retrieve data using id or pk in django

I am working on a project but after trying multiple ways I still couldn't find the solution. I need to get the current room on the page so that user can leave room, I am aware that it has to do with making queries or using pk,id. (My 1st question ever, sorry if it is not correct way to ask).
This is the code from Views.py:
def leave_room(request, room):
room = request.GET['room.pk']
room_details = Room.objects.get(name=room)
messages = Messages.objects.filter(room=room_details.pk)
membership = RoomMember.objects.filter(user=request.user, room=messages)
membership.delete()
return redirect("/")
urls.py:
path("leave/<int:pk>/join/", views.leave_room, name="leave_room"),
html:
<a class="btn btn-danger" href="{% url 'leave_room' pk=room.pk %}">Leave Room</a>
models.py:
class Room(models.Model):
name = models.CharField(max_length=100)
about = models.TextField(max_length=500, null=True, blank=True)
creator = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='room_creator')
members = models.ManyToManyField(User, through="RoomMember")
class RoomMember(models.Model):
approved = models.BooleanField(default=False, blank=False)
room = models.ForeignKey(Room, related_name='memberships', on_delete=models.CASCADE)
user = models.ForeignKey(User, related_name='user_groups', on_delete=models.CASCADE)
class Messages(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False)
text = models.CharField(max_length=10000, blank=False, null=False)
date = models.DateTimeField(default=datetime.now)
room = models.ForeignKey(Room, null=True, blank=False, on_delete=models.CASCADE)
Since you have a parameter <int:pk> the primary key of the room is passed through the pk parameter. This thus means that leave_room should be implemented as:
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
#require_POST
#login_required
def leave_room(request, pk):
nitems, __ = RoomMember.objects.filter(
user=request.user, room_id=pk
).delete()
if not nitems:
raise Http404
else:
return redirect('name-of-some-view')
The removal link is thus a mini form to make a POST request to the view:
<form method="post" action="{% url 'leave_room' pk=room.pk %}">
{% csrf_token %}
<button type="submit" class="btn btn-danger">Leave Room</button>
</form>
Note: Section 9 of the HTTP protocol
specifies that requests like GET and HEAD should not have side-effects, so you
should not change entities with such requests. Normally POST, PUT, PATCH, and
DELETE requests are used for this. In that case you make a small <form> that
will trigger a POST request, or you use some AJAX calls.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

Getting profile picture of blogposter in Django

When I display a blog post in HTML using a for loop
{% for post in posts %}
<div class="blogpost">
<h3><strong>{{post.title}}</strong></h3>
<img class="thumbnail" src="{{author.imageURL}}">
<h7>{{post.date}} - {{post.author}}</h7>
<br>
<hr>
<br>
{{post.context|linebreaks}}<br><br>
</div>
<br>
{% endfor %}
it works perfectly fine, except the authors profile picture does NOT get displayed.
I get the posts by getting all posts in my views.py from my models.py. The thing is that the profile picture of the user posting the blog isn't stored in the "post" model in the database. It is stored in the "Customers". Everybody should be able to read and post blogs. The admin (me) can later delete unwanted posts.
I have tried making a for loop using an array key:value in JavaScript. That is not very secure, because everybody just gets all users and all profilepictures through the whole database. That might not be a good idea.
This is my models.py
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank = True)
name = models.CharField(max_length=200, null=True)
email = models.EmailField(max_length=200, null=True)
about = models.CharField(max_length=100, null=True)
image = models.ImageField(null=True, blank=True)
#property
def imageURL(self):
try:
url = self.image.url
except:
url = 'placeholder.png'
return url
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200, null=True)
context = models.TextField(max_length=250, blank=True,
validators=[MaxLengthValidator(250)])
author = models.CharField(max_length=200, null=True)
from datetime import date
date = models.DateField(("Date"), default=date.today)
views.py
def homepage(request):
if request.user.is_authenticated: # Everybody has to be logged in
posts = Post.objects.all()
authors = Customer.objects.filter()
context = {'posts':posts, 'authors':authors}
return render(request, 'store/homepage.html', context)
That means that I want the user to see the persons profile picture in the corner of the blog post.
First I think you need to link the author in the Post model to a Customer with a foreignkey:
Then you can acces author fields like
{{ post.author.xyz }}
Currently your context contains authors as a queryset:
authors = Customer.objects.filter()
context = {'posts':posts, 'authors':authors}
But in your template you use it as if it were a single Customer:
<img class="thumbnail" src="{{author.imageURL}}">
And be aware of the typo "author" and "authors"
It is unclear what you meant by {{author.imageURL}} as author is QuerySet( that results in collection of authors).
You probably meant the related author to post which would be post.author
Other than that you should pass image URL to template and not ImageField string representation as documented
So it should be something in a line of
{{ post.author.imageURL.url }}

Unable to add a comment on my Django blog

I've been trying to add comments to the forum on my website and I've managed to get to the stage of being able to see the comment form. But, when you actually submit the comment form, I get the below error.
FYI, 'What Good Marketing Events are There in 2020?' is the name of the post I'm trying to add a comment too.
Here are the models used:
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments')
user_name = models.CharField(max_length=250)
email = models.EmailField()
content = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user_name
class Post(models.Model):
creator_id = models.ForeignKey(User, null=False, default=1)
title = models.CharField(max_length=200)
content = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
published_date = models.DateTimeField(blank=True, null=True, default=timezone.now)
views = models.IntegerField(default=0)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=30, blank=True, null=True)
image = models.ImageField(upload_to="img", blank=True, null=True)
def __str__(self):
return self.title
Here is the view used:
def comment_post_form(request, pk):
""" Create a view that allows us to add a comment """
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = CommentPostForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('forum_post_details.html', {'post': post})
else:
form = CommentPostForm()
return render(request, 'comment_post_form.html', {'form': form})
Here is the form used:
class CommentPostForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['content']
Here is the 'for' statement used in the template:
{% for comment in comments %}
<p>{{ comment.created_date }}</p>
<p>{{ comment.user_name }}</p>
<p>{{ comment.content }}</p>
{% empty %}
<p>No comments added. Why not be the first!</p>
{% endfor %}
Any help is greatly appreciated and if you need anything else, please let me know :)
The way you are redirecting is not how you do it. You can use the redirect() function in a number of ways.
url.py
path('teacherprofile/', views.teacher_profile_view, name='teacher-profile'),
views.py
By passing the name of a view
return redirect('teacher-profile')
By passing a hardcoded URL to redirect to:
return redirect(teacherprofile/)
This also works with full URLs:
return redirect('https://example.com/')
This way the user is redirect the html page itself.

Where is the data created from my form going?

I just created a form for the first time and have some questions regarding the process and where the data is going.
Here are my models, views, forms, urls, and templates files;
The model from models.py:
class Member(models.Model):
member_id = models.SlugField(max_length=10)
name = models.CharField(max_length=200)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
mobile = models.SlugField(max_length=20)
income = models.CharField(max_length=200, choices=INCOME_CHOICES)
education = models.CharField(max_length=200, choices=EDUCATION_CHOICES)
home_district = models.CharField(max_length=200, choices=DISTRICT_CHOICES)
family_spending = models.CharField(max_length=200, choices=FAMILY_SPENDING_CHOICES)
children_spending = models.CharField(max_length=200, choices=CHILDREN_SPENDING_CHOICES)
birth_date = models.DateTimeField('Birthday', blank=True)
comments = models.CharField(max_length=300, blank=True)
def __str__(self):
return self.name
views.py:
def create_a_member_form(request):
if request.method == 'POST':
form = MemberForm(request.POST)
if form is valid():
member_form = form.save()
return HttpResponseRedirect('/complete/')
else:
form = MemberForm()
return render(request, 'member_form.html', {'form': form})
forms.py:
from .models import Member
from django import forms
class MemberForm(forms.ModelForm):
class Meta:
model = Member
fields = '__all__'
urls.py:
urlpatterns = [
url(r'^member_form/$', views.create_a_member_form, name='member_form')
]
The template (member_form.html):
{% load staticfiles %}
<form action="/admin/" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
I want to know:
In the template, what does the /admin/ in <form action="/admin/" method="post"> represent? It's where the page redirects to after I click 'Submit', right?
Does the name='member_form' in urls.py represent the name of the HTML template the URL will match to, in thise case member_form.html?
Where is the data created from the form going? I've tried creating Member objects using the form but the new objects do not show up in my admin site under Members (while existing ones do). How do I make sure the objects created from this form do show up in my Admin site under Members?
Thank you.
Yes.
No, it's the name you use in a {% url %} tag if you want to generate a link pointing at that URL. The template is determined by the view itself (in render(request, 'member_form.html',...)).
It's not going anywhere, because your view is posting to /admin/ instead of /member_form/; /admin/ is the index of the admin site which has no code to actually accept your form data.
Note that 1 is basic HTML, and 2 and 3 are basic Django concepts which are covered in the tutorial; you should go and read that.

How to display fields of a M2M relation

I have this Django model:
#encoding:utf-8
from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin
# Create your models here.
class Profile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='user')
follows = models.ManyToManyField(User, related_name='follows', symmetrical=False, blank=True)
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatar', blank=True)
website = models.CharField(max_length=100, blank=True)
place = models.CharField(max_length=100, blank=True)
def __unicode__(self):
return unicode(self.user)
admin.site.register(Profile)
admin.autodiscover()
Then, I have this view:
def profile(request, user_id):
user = get_object_or_404(Profile, user=user_id)
return render_to_response('user_view.html', {'user':user,})
Now, in user_view.html I display the 'User' data (username, avatar, website, etc):
{{user.user_id}}
{{user.user}}
{{user.website}}
{{user.avatar.url}}
But, also I need to display the username, avatar and website of the users I follow. I did this:
{% for element in user.follows.all %}
{{element.user}}
<img src="{{element.avatar.url}} />
{% endfor %}
But, instead of display the user's data, it shows this:
<django.db.models.fields.related.RelatedManager object at 0x022F34F0>
But if I do this:
{% for element in user.follows.all %}
<p>{{element}}</p>
{% endfor %}
It shows perfectly the user's name, but I still cannot display the website or the avatar. How can I do this?
I think you would try
{% for element in user_data.follows.all %}
<p>{{element.username}}</p>
<p>{{element.profile.website}}</p>
<p>{{element.profile.avatar}}</p>
{% endfor %}
element is an instance of User and not an instance of Profile.
But you can still retrieve the associated Profile instance by writing
element.profile
because it's a One-To-One relationship (OneToOneField or ForeignKey(unique=True))

Categories