How to create a link in the Django website - django

I am working on the Django blog. I have created a url column in the admin post as follows.
however when I click the link in the page, the page jumps to the link which contains the localhost:8000 at the head of the url.
e.g. http://127.0.0.1:8000/Yahoo/www.yahoo.com
I made a link as Visit yahoo.com! however this is probably a wrong way to do it.
Can you please advise me how to fix this issue?
my class in model.py
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
updated_on = models.DateTimeField(auto_now= True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
url = models.CharField(max_length=200, unique=True, default='')
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
my html
{% extends 'base.html' %} {% block content %}
<div class="container">
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h1>{% block title %} {{ object.title }} {% endblock title %}</h1>
<p class=" text-muted">{{ post.author }} | {{ post.created_on }}</p>
<p class=" text-muted">{{ post.url }}</p>
Visit yahoo.com!
<p class="card-text ">{{ object.content | safe }}</p>
</div>
</div>
{% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %}
</div>
</div>
{% endblock content %}

http://127.0.0.1:8000/Yahoo/www.yahoo.com
This implies that the link you indicated was made relative to your current path:
Visit yahoo.com!
Making it absolute by adding a prefix slash would not help either as that would still reference to your current running server
Visit yahoo.com!
http://127.0.0.1:8000/www.yahoo.com
If the post.url is external and outside your server, append a prefix of http:// or https://
Visit yahoo.com!

Related

ValueError at / The 'pic' attribute has no file associated with it

I have a simple model with pic field having null and blank
class PostForNewsFeed(models.Model):
title = models.CharField(max_length=100, blank=True)
description = models.CharField(max_length=255, blank=True)
slug = models.SlugField(unique=True, max_length=100, blank=True)
pic = models.ImageField(upload_to='path/to/img', null=True, blank=True, default='')
{% if post.pic.url %}
<a href="{% url 'post-detail' post.id %}"
><img class="card-img-top" src="{{ post.pic.url }}" alt=""
/></a>
{% endif %}
When I submit without a pic I am getting the pic attribute not associated with a file.
My code seems fine in the template.
You should check if post.pic, not if post.pic.url:
{% if post.pic %}
<img class="card-img-top" src="{{ post.pic.url }}" alt=""/>
{% endif %}
Based on the discussion, in your template you use post.pic.url a lot of times when you work with template tags, etc. For example:
{% post_to_facebook post.pic.url "Post to Facebook" %}
you will need to make these conditional, since you can not fetch the .url of a post.pic if that post.pic is non existing.
You thus need to wrap this in an {% if … %} condition:
{% if post.pic %}
{% post_to_facebook post.pic.url "Post to Facebook" %}
{% endif %}

Django - how to get all the users in team when using a costumised user model

I am new to django and have a question: I created a CustomUser model within a users app.
I tried
from users.models import CustomUser, Team
team1= Team.objects.first()
users_team1= team1.user.objects.all()
and it doesnt get me the list of users in this Team
class CustomUser(AbstractUser):
bio= models.CharField(max_length=300, null= True, blank=True)
class Team (models.Model):
title = models.CharField(max_length=200)
user= models.ManyToManyField(get_user_model())
date_created= models.DateTimeField(auto_now_add=True, blank=True, null=True)
date_updated= models.DateTimeField(auto_now=True,blank=True, null=True )
def __str__(self):
return self.title
def get_absolute_url(self): # new
return reverse('team_detail', args=[str(self.pk)])
I want created a HTML page
{% extends '_base.html' %}
{% block title %}{{ object.title }}{% endblock title %}
{% block content %}
<div class="team-detail">
<h2>{{ team.title }}</h2>
<p>Team tile : {{ team.title }}</p>
<p>user: {{ team.user }}</p>
</div>
{% endblock content %}
how can i show all the users in a specific Team?
Thanks in advance.
You should do:
from users.models import CustomUser, Team
team1= Team.objects.first()
# lets pass team1 to your template
return render(request, 'template/name.html', {'team': team1})
Your template should be sthg like:
{% extends '_base.html' %}
{% block title %}{{ object.title }}{% endblock title %}
{% block content %}
<div class="team-detail">
<h2>{{ team.title }}</h2>
<p>Team tile : {{ team.title }}</p>
{% for user in team.user.all %}
<p>user: {{ user }}</p>
{% endfor %}
</div>
{% endblock content %}

Can't add normal Comment section in my Django web-application

I have trouble with adding comments to my django web-application. I want to add comments to allow users comment posts, like in normal web blog. I've tried a few ways, but nothing worked correctly for me.
After a few weeks searching and trying different ways to solve this question, I've stacked on this question. I have some progress, but it's now what I want completely.
Now I can only add "comments" from admin panel
and it look like this (from admin panel)
and like this (from user interface)
And I have this issue with padding comments( I don't really understand why it's occurs ¯_(ツ)_/¯ )
Anyway, here is my code, hope someone know how to solve this problem:
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField()
created_date = models.DateField(auto_now_add=True)
def __str__(self):
return self.text
...
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
categories = models.ManyToManyField('Category', related_name='posts')
image = models.ImageField(upload_to='images/', default="images/None/no-img.jpg")
slug= models.SlugField(max_length=500, unique=True, null=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'slug': self.slug})
post_detail.html
<article class="media content-section">
{% for comment in post.comments.all %}
<ul>
{{ comment.text }}
{% for reply in comment.replies.all %}
<li>
{{ reply.text }}
</li>
{% endfor %}
<ul>
{% endfor %}
</article>
I also read this article about creation blog for beginners, and they have working comment section as I want, but I tried to implement their code to my web-app, and nothing worked for me.
They have comment section like this (I need completely the same one):
But when I tried to follow their tutorial, I have only like this:
And here is the code for this unsuccessful solution( but I feel like it is working one, maybe I did something wrong)
post_detail.html
{% extends 'blog/base.html' %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}" alt="">
<div class="article-metadata">
<a class="mr-2 author_title" href="{% url 'user-posts' object.author.username %}">#{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted|date:"N d, Y" }}</small>
<div>
<!-- category section -->
<small class="text-muted">
Categories:
{% for category in post.categories.all %}
<a href="{% url 'blog_category' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</small>
</div>
{% if object.author == user %}
<div>
<a class='btn btn-secondary btn-sm mt-1 mb-1' href="{% url 'post-update' object.slug %}">Update</a>
<a class='btn btn-danger btn-sm mt-1 mb-1' href="{% url 'post-delete' object.slug %}">Delete</a>
</div>
{% endif %}
</div>
</article>
<article class="media content-section">
<div class="media-body">
<img class="img-fluid center" id="rcorners3" src="{{ object.image.url }}" alt="none">
<h2 class="article-title text-center">{{ object.title }}</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
<article class="media content-section">
<form action="/blog/{{ post.pk }}/" method="post">
{% csrf_token %}
<div class="form-group">
{{ form.author }}
</div>
<div class="form-group">
{{ form.body }}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<h3>Comments:</h3>
{% for comment in comments %}
<p>
On {{comment.created_on.date }}
<b>{{ comment.author }}</b> wrote:
</p>
<p>{{ comment.body }}</p>
<hr>
{% endfor %}
</article>
{% endblock content %}
views.py
...
def comment(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = Comment(
author=form.cleaned_data["author"],
body=form.cleaned_data["body"],
post=post
)
comment.save()
comments = Comment.objects.filter(post=post)
context = {
"post": post,
"comments": comments,
"form": form,
}
models.py
...
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField()
created_date = models.DateField(auto_now_add=True)
def __str__(self):
return self.text
forms.py
from django import forms
class CommentForm(forms.Form):
author = forms.CharField(
max_length=60,
widget=forms.TextInput(attrs={
"class": "form-control",
"placeholder": "Your Name"
})
)
body = forms.CharField(widget=forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Leave a comment!"
})
)
You are creating unnecessary lists. Try this one
<article class="media content-section">
<ul>
{% for comment in post.comments.all %}
<li>{{ comment.text }}</li>
{% if comment.replies.all %}
<ul>
{% for reply in comment.replies.all %}
<li>{{ reply.text }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
<ul>
</article>

why i am not getting a followed_by(followers) entry showing up on my page

i am making a twitter like clone(just to learn how things works in django)
so i am basically trying to set up a many_to_many relationship.
i want to add the functionality of showing 'FOLLOWED_BY' and 'FOLLOWING' to a user profile but list of 'FOLLOWED_BY' is not showing on the page please someone help me!
in the models.py i have define two relationship
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL, related_name='profile', null=True,
blank=True)
following = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='followed_by', blank=True)
and in the user_detail.html i have the code for how a profile should look like
this is the models.py module:
from django.conf import settings
from django.db import models
# Create your models here.
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL, related_name='profile',
null=True,
blank=True)
following = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='followed_by', blank=True)
def __str__(self):
return str(self.following.all().count())
below is the code for user_detail.html file:
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="col-sm-3 col-xs-12" style="background-color: yellow">
<h1>{{ object.username }}</h1>
<p>Followers: {{ object.followed_by.count }}</p>
</div>
<div class="col-sm-9 col-xs-12">
<h1>Tweets</h1>
{% for tweet in object.tweet_set.all %}
{{ tweet }}<br/>
{% endfor %}
<hr/>
<h1>Following</h1>
{% for user in object.profile.following.all %}
<a href='/{{ user.username }}'>{{ user.username }}</a><br/>
{% empty %}
<h4>Not following any users</h4>
{% endfor %}
<hr/>
<h1>Followed By</h1>
{% for profile in object.profile.followed_by.all %}
<a href='/{{ profile.user.username }}'>{{ profile.user.username }}</a><br/>
{% empty %}
<h4>Not followed by any user</h4>
{% endfor %}
</div>
{% endblock content %}
for user profile i am getting the FOLLOWING field as i want but FOLLOWED_BY field is not showing how can i do that (what changes should i do in my code)??
You defined a following field that points to the user model, not to a Profile. As a result a Profile has no followed_by relation, a User object has.
I think it probably is better to let following point to Profile, like:
class UserProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
related_name='profile',
null=True,
blank=True
)
following = models.ManyToManyField(
'self',
related_name='followed_by',
symmetrical=False,
blank=True
)
def __str__(self):
return str(self.following.all().count())
Then you can render this like:
<div class="col-sm-3 col-xs-12" style="background-color: yellow">
<h1>{{ object.username }}</h1>
<p>Followers: {{ object.followed_by.count }}</p>
</div>
<div class="col-sm-9 col-xs-12">
<h1>Tweets</h1>
{% for tweet in object.tweet_set.all %}
{{ tweet }}<br/>
{% endfor %}
<hr/>
<h1>Following</h1>
{% for profile in object.profile.following.all %}
<a href='/{{ profile.user.username }}'>{{ profile.user.username }}</a><br/>
{% empty %}
<h4>Not following any users</h4>
{% endfor %}
<hr/>
<h1>Followed By</h1>
{% for profile in object.profile.followed_by.all %}
<a href='/{{ profile.user.username }}'>{{ profile.user.username }}</a><br/>
{% empty %}
<h4>Not followed by any user</h4>
{% endfor %}
</div>
Your code has however some (serious) anti-patterns. The most important one is that you should not write business logic in the template. You should use the view for that. For example you can specify in the view a context like:
context = {
'tweets': object.tweet_set.all()
'followers': object.profile.following.select_related('user').all()
'followed_by': object.profile.followed_by.select_related('user').all()
}
We here can also use a .select_related() [Django-doc] that will boost performance significantly, since now all the users are fetched in the same query.
You also better use the {% url ... %} template tag [Django-doc] to construct queries. So instead of writing:
<a href="/{{ profile.user.username }}">
it is better to construct the query using a reverse lookup like:
<a href="/{% url 'profile_view' username=profile.user.username %}">

Reverse for 'profile_update' with arguments '(1,)' not found. Issue

I have a base url link to access a profile edtting screen but it seems to break my application.
Ive tried so many things that i am getting confused by the different views. I was able to get the form appearing previously but have somehow broken it.
from my base.html(if i remove this line the app start to work again). Im not sure about this user.id parameter im passing in this - is it needed?
<li class="nav-item">
<a class="nav-link" href="{% url 'accounts:profile_update' user.id %}">Edit Profile</a>
</li>
my urls file:
path('profile/edit/', views.ProfileCreate.as_view(), name='profile_update'),
my model:
class Profile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='userprofile')
houseNumber = models.CharField(max_length=150, default='')
street = models.CharField(max_length=150, default='')
suberb = models.CharField(max_length=150, default='')
city = models.CharField(max_length=150, default='')
phone = models.CharField(max_length=150, default='')
def __unicode__(self):
return self.user.get_full_name()
def __str__(self):
return self.user
def get_absolute_url(self):
return reverse('account:profile', kwargs=[self.pk])
my form:
class ProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
class Meta:
model = Profile
fields = ['user', 'houseNumber', 'street', 'suberb', 'city', 'phone']
the html for the form:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<div class="container">
<form enctype="multipart/form-data" action="{% url 'accounts:profile_update' %}" method="post" novalidate>
{% csrf_token %}
{{ form|crispy }}
<input name="Submit" type="submit" class="btn btn-success" value="Save"></input>
</form>
<p></p>
</div>
{% endblock %}
Apologies if this question is similar to a few others Ive asked but i just had to restart with this form using a different approach because it just wasnt working properly previously.
According to you url, you don't need to pass user.id through update_profile. So please change the code to:
<a class="nav-link" href="{% url 'accounts:profile_update' %}">Edit Profile</a>