Bringing Information from django.contrib.auth.models.User into View - python

I have the following model in my Django project:
from django.contrib.auth.models import User
class Project(models.Model):
project_title = models.CharField(max_length=200)
project_description = models.CharField(max_length=200, default="")
created_date = models.DateTimeField('date created')
owner = models.ForeignKey(User)
def __str__(self):
return self.project_title
This view uses the Project model as follows:
class ProjectView(generic.edit.UpdateView):
model = Project
fields = ['project_title','project_description']
template_name = 'steps/project.html'
success_url = reverse_lazy('steps:index')
My question is how can I bring the User's fields into my ProjectView so I can then use them in templates? In particular, I would like to display the logged-in user's name and email.

user information placed on request, not on views. So you can write in template {{user.username}}, or {{user.email}}. and you'll get it. Of course if user.is_authenticated

in your template write:
{% if request.user.is_authenticated %}
{{ request.user.username }}
{{ request.user.email }}
{% endif %}

Related

Django: get_context_data for comments related post

I have a models:
class Post(models.Model):
post_text = models.CharField(max_length=100, unique=True)
slug = models.SlugField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
class Comment(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author')
post_relation = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='comments')
comment_text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
In my views I need get comments for posts in get_context_data:
class ResultsView(DetailView, FormMixin):
model = Post
template_name = 'posts.html'
form_class = CommentForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comm'] = Comment.objects.filter(is_active=True)
return context
But in comm i get all comments in db.
In html:
{% for comment in question.comments.all %}
<div class="media mb-4">
<div class="media-body">
<h5 class="mt-0">{{ comment.author }}</h5>
{{ comment.comment_text }}
</div>
</div>
{% endfor %}
I try {% for comment in comm %}, try {% for comment in comm.all %} and always get all comments in db, not only comments in post.
Also I try fix this string in views: context['comm'] = Comment.objects.filter(is_active=True), but don't have a result.
The answer seems to be very simple, but I've already spent several hours trying and reading.
You can filter with:
class ResultsView(FormMixin, DetailView):
model = Post
template_name = 'posts.html'
form_class = CommentForm
def get_context_data(self, **kwargs):
return super().get_context_data(
**kwargs, comms=self.object.comments.filter(is_active=True)
)
and then render with:
{% for comment in comms %}
# …
{% endfor %}
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: The related_name=… parameter [Django-doc]
is the name of the relation in reverse, so from the User model to the Comment
model in this case. Therefore it (often) makes not much sense to name it the
same as the forward relation. You thus might want to consider renaming the author relation to comments.

Select2 widget showing on Django Admin site but not on the form template in Django4

I have two object models, NewsObject and StockObject. The stock object is a foreign key in the news object.
class stockObject(models.Model):
stock_name = CharField(max_length=100, blank=True, null=True)
stock_tag = CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.stock_name
class newsObject(models.Model):
title = CharField(max_length=100, blank=True, null=True)
body = TextField(blank=True, null=True)
stock = ForeignKey(stockObject, on_delete=models.SET_NULL, blank=True, null=True)
I have used autocomplete_fields property in the ModelAdmin class as I want a searchable dropdown for stocks in news. I have also added search_fields in the stocks ModelAdmin as mentioned in the documentation.
This is what my admin.py looks like:
class stockAdmin(admin.ModelAdmin):
list_display = ['stock_name', 'stock_tag']
search_fields = ['stock_name']
class newsAdmin(admin.ModelAdmin):
list_display = ['title', 'body', 'stock']
search_fields = ['title', 'body', 'stock']
autocomplete_fields = ['stock']
Now, the issue is that I get a searchable dropdown on the Django Admin site for this field, but it is only a dropdown (not searchable) on the actual template screen. I have a basic view which calls the template, like so:
Views.py
def createNews(request):
form = NewsForm()
if request.method == 'POST':
form = NewsForm(request.POST)
if form.is_valid():
form.save()
return redirect('/backoffice/')
context = {'form' : form}
return render(request, 'NewsForm.html', context)
And NewsForm.html is:
{% extends "base.html" %}
{% load static %}
{% block content %}
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" name="Submit">
</form>
{% endblock %}
I've been wondering what might be the cause of this behavior. Tried multiple things but none of them work. What might I be missing here?
Django Admin site image
Django Template Image
I think you have written all your models in camelCase so first changed them to PascalCase.
Second, you have missed models in all your models:
Write them like this add models before every datatype like:
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
Not only datatype of fields.

How do i query for comment in Django

I am new in Django and I have been following tutorials online. I am having problem on how to display the comments.
How do i query for comments in views, so i can display comments for a particular post.
Model:
class Post(models.Model):
poster_profile = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, blank=True,null=True)
image_caption = models.TextField(blank=True, null=True)
class Comments (models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, blank=True,null=True)
commented_image = models.ForeignKey(Post, on_delete=models.CASCADE, null=True, blank=True)
comment_post = models.TextField()
Views.py:
def home_view(request):
comment = Comments.objects.all() #This is getting all comment in all post, how do i query for comment in a particular post.
context{'comment':comment}
return render(...)
Template:
{% for com in comment %}
<p>{{ com.comment_post }}</p>
{% endfor %}
You can do
post = Post.objects.get(id=1)
comment = post.comments_set.all()
Following Relationships "Backward"
If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased. This Manager returns QuerySets, which can be filtered and manipulated as described in the “Retrieving objects” section above.
Note this behaviour can be overridden.
You can override the FOO_set name by setting the related_name parameter in the ForeignKey definition. For example, if the Entry model was altered to blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries'), the above example code would look like this:
Edit #2:
views.py:
def home_view(request):
posts = Post.objects.all().reverse()[5]
context{ 'posts': posts, }
return render(...)
Now in your templates you can do something like:
{% if posts %}
{% for post in posts %}
{{ post.image_caption }}
{% for comment in post.comments_set.all %}
{{ comment.comment_post }}
{% endfor %}
{% endfor %}
{% endif %}
First of all, take a look at Django queryset documentation, especially select_related for this kind of issues (to reduce number of queries to database). I didn't try but following snippet must work.
class Post(models.Model):
poster_profile = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
image_caption = models.TextField(blank=True, null=True)
class Comments (models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
commented_image = models.ForeignKey(Post, related_nam="comments", on_delete=models.CASCADE)
comment_post = models.TextField()
...
def home_view(request):
post = Post.objects.filter(id=request.data.get('post_id')).select_related("comments") # specify the post anyhow ..
comments = post.comments
context{'comment': comments}
return render(...)
def home_view(request):
particular_Post= Post.objects.get(id=1)
comment = Comments.objects.get(Post=particular_Post)
context{'comment':comment}
return render(...)
to understund Query in django i suggest U to start by
python manage.py shell
and Import you're Models

How to create new issues without selecting 'project'(manually select project_id)?

I am doing my school project by using Django to create a task management web application. My responsibilities are to create 'issue tracker', something like 'StackOverflow', but I am still at the very early stage of it. So I used crispy form to let the user create their own new issues. Since we use 'project_id' and 'issue_id' as parameters to direct users to different pages, so I encountered this problem, users have to manually choose 'project' when they create a new issue. I do not know how to put the issue which created by the user under right project without having to choose 'project' manually.
form.py
from django import forms
from .models import Comment,Issue
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('body',)
class IssueForm(forms.ModelForm):
class Meta:
model = Issue
fields = ('title','content','project','status')
class NewIssueForm(forms.ModelForm):
class Meta:
model = Issue
fields = ('title','content','project','status')
new_issue.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Add New Issue </h1>
<form method="POST" class="Issue-form">{% csrf_token %}
{{form|crispy}}
<button type="submit" class="btn btn-success">Submit</button>
</form>
{% endblock %}
models.py
class Issue(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
project = models.ForeignKey(Project,on_delete=models.CASCADE)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
published = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=9, choices=STATUS_CHOICES, default='draft')
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Issue, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('project:issue_tracker:issue_detail', kwargs={'project_id':self.project_id, 'issue_id':self.id})
def __str__(self):
return self.title
urls.py
urlpatterns =[
path('',views.list_of_issue,name='list_of_issue'),
path('<int:issue_id>/',views.issue_detail,name='issue_detail'),
path('<int:issue_id>/comment',views.add_comment,name='add_comment'),
path('new_issue/',views.new_issue,name='new_issue'),
path('<int:issue_id>/edit_issue/',views.edit_issue,name='edit_issue'),
path('<int:issue_id>/delete_issue/',views.delete_issue,name='delete_issue'),
path('<int:issue_id>/delete', TemplateView.as_view(template_name="issue_tracker/issue/nice_delete.html"), name='success_deletion'),
]
You can set an initial value for the project field in the issue form. An explanation of how that can be done can be found here.
Since you are using project_id and issue_id as parameters, something similar to the following will solve your problem (I guess):
def new_issue(request, project_id, issue_id):
.
.
form = IssueForm(initial={'project': project_id})
.
.

django specific user content/data

I'm trying to display specific content/data based on a logged in user. I want to display only their info. This is what I've tried but I can't get it to work.
views.py
class DemoView(TemplateView):
template_name = 'demographics/demographics.html'
def get(self, request):
demos = Demographics.objects.filter(user=request.user)
context = {
'demos': demos,
}
return render(request, self.template_name, context)
models.py
class Demographics(models.Model):
first_name = models.CharField(max_length=50, null=True)
middle_name = models.CharField(max_length=50, null=True)
last_name = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True)
HTML
{% if demos %}
{% for demographics in demos %}
<p>First Name</p> {{ demographics.first_name }}
{% endfor %}
{% else %}
<h3>you dont have demo yet</h3>
{% endif %}
I feel like I'm close. What am I missing?
I think the issue may be that you are filtering out all answers from your queryset because the content of request.user is not quite a match for a 'user' object. I don't know why they wouldn't match, but in my code I use:
User.objects.get(username = request.user.username)
I think debugging using pdb will help why the get is not rendering the data properly but if you know how django templateview class handles the context data, you have to modify the code a bit. Here I used get_context_data instead of get and hope this time it will work.
class DemoView(TemplateView):
template_name = 'demographics/demographics.html'
def get_context_data(self, **kwargs):
context = super(DemoView, self).get_context_data(**kwargs)
demos = Demographics.objects.filter(user=self.request.user)
context['demos'] = demos
return context
Also you can check if the table Demographics has the data for the selected user.
full Answer:
Views.py
class DemoView(TemplateView):
template_name = 'demographics/demographics.html'
def get(self, request, *args, **kwargs):
demos = Demographics.objects.filter(user=User.objects.get (username=request.user))
context = {
'demos': demos,
}
return render(request, self.template_name, context)
HTML:
{% if demos %}
{% for demographics in demos %}
<p>First Name</p> {{ demographics.first_name }}
{% endfor %}
{% else %}
<h3>you dont have demo yet</h3>
{% endif %}
urls.py
url(r'^test/', views.DemoView.as_view()),
admin.py
admin.site.register(Demographics)
models.py
class Demographics(models.Model):
first_name = models.CharField(max_length=50, null=True)
middle_name = models.CharField(max_length=50, null=True)
last_name = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True)
Go to django admin, check your objects, and make sure you're logged in to the account that has demographic objects associated with it.
The above setup works for me, if it doesn't work for you, you're most likely logged in as a user which doesn't have any demographic objects associated with it.
Also, don't name your models as plural, it should be Demographic, because it is a representation of one object. When you filter in views, you name the variable demographics (plural), because the query returns more than one object.

Categories

Resources