My models.py:
class Mymodel(models.Model):
title = models.CharField(max_length=32)
other_useful_field = models.CharField(max_length=32)
...
secret_field = models.CharField(max_length=32)
My views.py:
def myview(request):
context_dict=[]
context=Mymodel.objects.get(id=1)
context_dict=['reserved_data'] = context
return render(request, 'mytemplate.html', context_dict)
My mytemplate.html:
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}{{ reserved_data.title }}{% endblock %}
{% block content %}Hello world{% endblock %}
Is there a (simple*) method for a user to read all 'reserved_data'?
Can a user have access to secret_field?
I don't want that to happen.
*simple, I mean a good hacker eventually can have access to all data anyway...
The template is rendered on the server and output as HTML for the user to see. The user never sees the raw template. As long as your server is secure you have nothing to worry about.
Related
I have these two models and as you can see they have a relationship.
class Post(models.Model):
text = models.TextField()
class PostImage(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
image = models.FileField(upload_to = 'media/',blank=True, null=True)
As far as I understand if I query posts and push them to a template and post, I would expect to use something like this in my templates to retrieve the images URL attached to the posts but it doesn't seem to work.
{% for post in posts %}
{% for post_image in post.post_image_set.all %}
{{post_image.image.url}}
{% endfor %}
{% endfor %}
What am I doing wrong?
Here is my views.py file.
views.py
# Create your views here.
def index(request):
posts=Post.objects.filter(approved=True).order_by('-published_date')
context = {"posts":posts}
return render(request, 'post/home.html',context)
The default related name for a foreign key relational is the name of the model (PostImage) but in your template for loop you called it post_image Following relationships “backward”
change
{% for post_image in post.post_image_set.all %}
into
{% for post_image in post.postimage_set.all %}
Template code (with change)
{% for post in posts %}
{% for post_image in post.postimage_set.all %}
{{post_image.image.url}}
{% endfor %}
{% endfor %}
Basically, I'm writing an app in which people can make blog and image posts. So far, I've completed users to be able to write text posts. However, when I try to create a post, it returns "By: None" when it should be returning "By: shrey". In this case, Bob is the author. Here's an image:
Here's an image for the post creation view:
Theoretically, when I enter a post it should say who it was written by.
Here's the template for the create post:
{% extends "social/base.html" %}
{% load crispy_forms_tags %}
{% block content4 %}
<h1>Make Your Post</h1>
<p>Write a post / Share an image</p>
<br>
<div class="container">
<form method="post">
{% csrf_token %}
{{form|crispy}}
<button type="submit" name="button">Make Post</button>
</form>
</div>
{% endblock content4 %}
Here's the function for the create post view:
class PostCreateView(CreateView):
model = Posts
fields = ['post_title', 'post_text_content']
def form_valid(self, form):
form.instance.author = self.request.user
print(self.request.user)
return super().form_valid(form)
Thank you in advance.
EDIT: Home Page Template (template which displays the posts):
{% extends "social/base.html" %}
{% block content %}
<h1>Your Feed</h1>
<p>This is your feed. Here, you'll see posts from people you follow.</p>
{% if user.is_authenticated %}
<p>You are logged in as {{user.username}}. This is your feed.</p>
{% else %}
<p>You are not logged in. This is a random feed.</p>
{% endif %}
{% for post in posts %}
<h1>{{ post.post_title }}</h1>
<p>By {{ post.post_author }} on <i>{{ post.post_date }}</i></p>
<p>{{ post.post_text_content }}</p>
{% endfor %}
Click here to make a post.
<br>
Click here to logout.
<br>
Click here to login.
<br>
Click here to sign up and make an account.
<!--<p>Want to post something? Enter your info here: </p> -->
{% endblock content %}
Posts Model:
class Posts(models.Model):
post_title = models.CharField(max_length = 40, help_text = 'Enter post title')
post_text_content = models.TextField(max_length = 1000)
post_author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
post_date = models.DateField(auto_now = True, auto_now_add = False)
#Make optional Image Field
class Meta:
ordering = ['post_title', 'post_author', 'post_date', 'post_text_content']
def __str__(self):
return self.post_title
def get_absolute_url(self):
return reverse('social-home')
The name of the field is post_author, not author, hence you should set post_author:
class PostCreateView(CreateView):
model = Posts
fields = ['post_title', 'post_text_content']
def form_valid(self, form):
form.instance.post_author = self.request.user
return super().form_valid(form)
That being said, normally in Django one does not prefixes the model fields with the name of the model. One reason not to do that is that you can define abstract models where you define the field once, and then use inheritance to add the field to other models.
I have an application with a user follower system which I have been able to achieve but I try to retrieve individual user followers and following but I could not get it. Below is my code
View.py
def following(request):
query = Contact.objects.filter(request.user.following)
context = {
'query': query
}
template = 'following.html'
return render(request, template, context)
Models.py
class Contact(models.Model):
user_from = models.ForeignKey(User,related_name='rel_from_set')
user_to = models.ForeignKey(User,related_name='rel_to_set')
created = models.DateTimeField(auto_now_add=True,db_index=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return '{} follows {}'.format(self.user_from,self.user_to)
User.add_to_class('following',models.ManyToManyField('self', through=Contact,related_name='followers', symmetrical=False))
Template
{% load staticfiles %}
{% block content %}
<h2>following</h2>
<div id="action-list">
<h1>{{ results.get_full_name }}</h1>
</div>
{% endblock %}
Additional code would be added on request.
This could be solved two ways. First: your filter is not correct:
def following(request):
query = Contact.objects.filter(user_from=request.user)
context = {
'query': query
}
template = 'following.html'
return render(request, template, context)
Another solution with the reverse relation using the related_name
def following(request):
query = request.user.rel_from_set.all()
context = {
'query': query
}
template = 'following.html'
return render(request, template, context)
Works similar, of course, for the user_to field of Contact.
EDIT: Your template doesn't use the proper context variables you have defined in view following. So you'll need to tweak it a bit:
{% load staticfiles %}
{% block content %}
<h2>following</h2>
<div id="action-list">
{% for result in query %}
<h1>{{ result }}</h1>
{% endfor %}
</div>
{% endblock %}
One of my tables in my app is called Gallery and I have the following class to list all of the objects on that table:
from django.views.generic import ListView
from galleries.models import Gallery
class GalleryList(ListView):
template_name = "path/to/template"
context_object_name = "object_list"
def queryset(self):
return Gallery.objects.order_by('-title')[:20]
And it does the job. On my template I do the following:
{% block gallery_list %}
<h1>Gallery List</h1>
<ul>
{% for gallery in object_list %}
<li><img src="{{ gallery.thumbnail.url }}" />{{ gallery.title }}</li>
{% endfor %}
</ul>
{% endblock %}
Everything works as expected. The thing here is that on my base.html template I have {% block title %} for the meta title tag, {% block description %} for my meta description tag in the header. And I want to be able to declare it somewhere and pass it to the view. To be clear, the variables title and description are strings (ex: title="List of all galleries on website").
On the view I want to do something like:
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block description %}{{ description|default:title }}{% endblock %}
But, on the class GalleryList I don't know where to declare the variables title and description. I don't know if that's possible or proper for Django. I want to do what's right.
Also, as I have a costume template for listing all the galleries I could just do:
{% extends "base.html" %}
{% block title %}List of all galleries on website{% endblock %}
{% block description %}List of all galleries on website...{% endblock %}
But then again, I don't know if that's proper for a well coded Django app. I'm a beginner with Django and I would like to know what's the way to go about this. Hope my question is clear enough.
You can override the ListViews get_context_data method to add whatever additional context variables to you want to the context:
class GalleryList(ListView):
def get_context_data(self, **kwargs):
ctx = super(GalleryList, self).get_context_data(**kwargs)
ctx['title'] = 'My Title'
ctx['description'] = 'My Description'
return ctx
The other approach - of having a template that fills in this information - is also sound. Which is better really depends on how dynamic the data is. If the title/description is based on model data or some other factors, then it makes sense to set it in the view. If it is fixed for a particular template then it is probably cleaner to put in in a template that extends base.html.
I have a Django app that contains info on schools and states. I want my template to display a list of schools per state and also the name of the state based on the state parameter in the URL. So if a user goes to example.com/vermont/ they will see a list of Vermont schools and a tag that says they're on the "Vermont" page. I can get the list of schools per state to work, but I can't figure out how to simply list the state name in the h1 tag.
Here is my models.py:
from django.db import models
class School(models.Model):
school_name = models.CharField(max_length=200)
location_state = models.CharField(max_length=20)
def __unicode__(self):
return self.school_name
Here is my views.py:
from django.views.generic import ListView
class StateListView(ListView):
model = School
template_name = 'state.html'
context_object_name = 'schools_by_state'
def get_queryset(self):
state_list = self.kwargs['location_state']
return School.objects.filter(location_state=state_list)
And here's my template for state.html:
{% extends 'base.html' %}
{% block content %}
<h1>{{school.location_state }}</h1> [THIS IS THE LINE THAT DOES NOT WORK]
{% for school in schools_by_state %}
<ul>
<li>{{ school.school_name }}</li>
</ul>
{% endfor %}
{% endblock content %}
What am I missing here?
The problem is that the school variable never enters the context. You are only setting the schools_by_state to the context.
To add some extra context you need to override the get_context_data method. This way you can add the location_state from the url parameter:
def get_context_data(self, **kwargs):
context = super(StateListView, self).get_context_data(**kwargs)
context.update({'state': self.kwargs['location_state']})
return context
Then you can use the {{ state }} instead of {{ school.location_state }} in your template.