I have a model called Post. The data in Post is displayed to every user while I want this to be user specific.
I'm new to Django. This app is created following the Django for Girls tutorial. I later added support for user registration.
models.py:
from django.conf import settings
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
Example from views.py:
from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from .models import Post
from .forms import PostForm
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, authenticate
#login_required
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
Example from the template (post_list.html):
{% for post in posts %}
<div class="post">
<div class="date">
<p>published: {{ post.published_date }}</p>
</div>
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
Change your filter to filter by user as well as published_date:
posts = Post.objects.filter(
published_date__lte=timezone.now(),
author=request.user
).order_by('published_date')
Inside your class/function view check if the user is authenticated.
if not request.user.is_superuser:
raise Http404
Also check this
Related
I'm following along a book called Django for Beginners and creating a project which displays newspaper articles. Part of the functionality is being able to edit those articles. I've followed along as closely as I could but I'm still getting an error when hitting the 'Update' button:
My urls.py
from django.urls import path
from .views import (ArticleListView,
ArticleUpdateView,
ArticleDetailView,
ArticleDeleteView)
urlpatterns = [
path('<int:pk>/edit/', ArticleUpdateView.as_view(), name = 'article_edit'),
path('<int:pk>/', ArticleDetailView.as_view(), name = 'article_detail'),
path('<int:pk>/delete/', ArticleDeleteView.as_view(), name = 'article_delete'),
path('', ArticleListView.as_view(), name = 'article_list'),
]
my views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Article
# Create your views here.
class ArticleListView(ListView):
model = Article
template_name = 'article_list.html'
class ArticleDetailView(DetailView):
model = Article
template_name = 'article_detail.html'
class ArticleUpdateView(UpdateView):
model = Article
fields = ('title', 'body')
template_name = 'article_edit.html'
class ArticleDeleteView(DeleteView):
model = Article
template_name = 'article_delete.html'
success_url = reverse_lazy('article_list')
My models.py:
from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
from django.urls import reverse
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=225)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
)
def __str__(self):
return self.title
def get_absolute_url(self):
reverse('article_detail', args=[str(self.id)])
My HTML:
<!-- templates/article_edit.html -->
{% extends 'base.html' %}
{% block content %}
<h1>Edit</h1>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}\
<button class="btn btn-info ml-2" type="submit">Update Article {{article.pk}}</button>
</form>
{% endblock content %}
After hitting the edit button, according to the book the app is supposed to forward me to the 'article_detail' page however that is not happening.
Any assistance would be gratefully received.
Thanks
Andy
In the end it was a simple omission of a return statement in the get_absolute_url function within models.py.
I am having a post model with a user having OneToMany Relationship with inbuilt user model for authentication
my urls.py
from django.contrib import admin
from django.urls import path, include
# from views import PostView
from . import views
urlpatterns = [
path('', views.PostView.as_view(), name='blogHome'),
path('post/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
path('post/new/', views.PostCreateView.as_view(), name='post-create'),
path('about/', views.about, name='about')
]
my views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Post
from django.views.generic import (
ListView,
DetailView,
CreateView
)
# Create your views here.
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
def about(request):
return render(request, 'blog/about.html')
class PostView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_published']
class PostDetailView(DetailView):
model = Post
class PostCreateView(CreateView):
model = Post
fields = ['title', 'body']
#to add author before validation
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
Post Model
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
# Create your models here.
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
body = models.TextField()
date_published = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
I am using post_form.html as the template name
post_form.html
{% extends 'blog/layout.html' %}
{% load crispy_forms_tags %}
{% block body %}
<div class="content-section p-20">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group p-30">
<legend class="border-bottom mb-4">Create new post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Create</button>
</div>
</form>
</div>
{% endblock %}
I am a beginner in Django , please tell if anything more is needed to solve the problem. Also why this type of error is coming only with Createview and not with other views
Apparently the return of super().form_valid(form) is None and not a valid response. I don't know much of this design pattern in Django but seeing your other methods seems like this view is decorated by some method which returns a valid response. So you should not return something in your implementation. So, drop the return and test again.
I am building a web app in Django trying to use django-autocomplete-light(v.3.8.2) to create an auto-complete field. I have form that allows users to create a Trade record. I'm trying to add an auto-complete field for Trade.owned_game (a lookup field). I am just getting an empty dropdown field for the auto-complete field (screenshot attached at bottom of this post) Below is my code:
models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Game(models.Model):
name = models.TextField() # Unrestricted text
platform = models.CharField(max_length=100) # character field
created_date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name # return game name when game.objects.all() is called
class Trade(models.Model):
name = models.TextField() # Unrestricted text
created_date = models.DateTimeField(default=timezone.now)
is_trade_proposed = models.BooleanField(default=False)
user_who_posted = models.ForeignKey(User, on_delete=models.CASCADE)
owned_game = models.ForeignKey(Game, on_delete=models.CASCADE, related_name='owned_game', db_column='owned_game')
def __str__(self):
return self.name # return game name when game.objects.all() is called
urls.py:
from django.urls import path
from django.conf.urls import url
from .views import (
PostListView,
TradeListView,
PostDetailView,
TradeCreateView,
GameAutoComplete,
PostUpdateView,
PostDeleteView,
UserPostListView
)
from . import views
urlpatterns = [
path('', views.home, name='blog-home'),
path('post/new/', views.trade_new, name='trade-create'),
url(
r'^game-autocomplete/$',
GameAutoComplete.as_view(),
name='game-autocomplete')
,
]
views.py:
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
from .models import Trade, Game
def trade_new(request):
form = TradeCreateForm()
return render(request, 'blog/trade_form.html', {'form': form, 'title': 'asdf'})
class TradeCreateForm(forms.ModelForm):
game = forms.ModelChoiceField(
queryset=Game.objects.all(),
to_field_name = 'name',
widget=autocomplete.ModelSelect2(url='game-autocomplete')
)
class Meta:
model = Trade
fields = ['owned_game', 'desired_game']
class TradeCreateView(LoginRequiredMixin, CreateView):
model = Trade
fields = ["owned_game"]
class GameAutoComplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Game.objects.none()
qs = Game.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
trade_form.html:
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Propose New Trade</legend>
{{ form|crispy }}
{{ form.media }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit</button>
</div>
</form>
</div>
{% endblock content %}
Screenshot:
enter image description here
I have tried the solutions from these similar StackOverflow questions but they're not working:
Django-autocomplete-light showing empty dropdown instead of autocomplete widget
django-autocomplete-light displays empty dropdown in the form
I should have checked the javascript console earlier! The problem was one of the <link ...> scripts for jQuery was invalid. Once i fixed that, the auto-complete field worked
I am new to the community. I usually am able to just find my answer, but I have been searching and searching, and can't seem to find anything similar to what I've got going on. I have a ModelForm set up to register new users. I got it to work, and send information over to the sqlite database. However, when I try to log the newly registered user in it says:
"Please enter a correct username and password. Note that both fields may be case-sensitive."
login.html:
{% extends 'app/register.html' %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Login">
</form>
Back to Homepage
<br>
Reset password
<br>
Register
{% endblock %}
views.py
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.decorators import login_required
from datetime import datetime
from django.http import HttpRequest
from django.shortcuts import render, redirect
from django.urls import reverse
from . import forms
from django.contrib import auth
def index(request):
"""Renders the home page."""
assert isinstance(request, HttpRequest)
return render(
request,
'app/index.html',
{
'title':'Home Page',
'year':datetime.now().year,
}
)
def register(request):
if request.method == "GET":
form = forms.Registration(request.GET)
return render(
request, "app/register.html",
{"form": form}
)
elif request.method == "POST":
form = forms.Registration(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect(reverse("index"))
models.py
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class Patient(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
#birthdate = models.DateField(auto_now=False, null=True, blank=True)
gender = models.CharField(max_length=100, blank=True)
allergies = models.TextField(blank=True)
email = models.CharField(max_length=200)
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
last_login = models.CharField(max_length=100)
and forms.py:
from django import forms
from . import models
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
class Registration(forms.ModelForm):
class Meta:
model = models.Patient
fields = ('first_name','last_name', 'gender', 'email', 'username', 'password', 'allergies',)
any help would be greatly appreciated. Please forgive me if I've left something out, just let me know. Thank you!
In line 33 in the views file you used auth_login() function but I could not find where you imported it
did you mean authentication() or login() functions?
So after a lot of trial and error and fiddling, I ultimately fixed it this way, thanks to Abdul Aziz Barkat's suggestion above.
I changed Patient(models.Model) to Patient(AbstractUser)
And then I also had to change the Registration(forms.ModelForm) to Registration(UserCreationForm). All of the users are authenticating just fine now, thank you!
I have used django's models and forms to add a comment section to a blog app, however the form's text field will not show when loaded in the in the browser. Only the submit button loads with no textfield to submit with.
models.py
from django.db import models
from datetime import datetime
from django import forms
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.TextField()
date = models.DateTimeField("date published", default=datetime.now())
def _str_(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('blog.post', on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=100)
text = models.TextField(max_length=200)
created_date = models.DateTimeField(default=datetime.now())
def _str_ (self):
return self.text
forms.py
from django import forms
from django.forms import ModelForm
from .models import Comment
from django.db import models
class CommentForm(forms.ModelForm):
class Meta:
models = Comment
exclude = ['post']
form = CommentForm
post.html
<div>
<div class="container">
<h5>New comment</h5>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<br>
<button class="btn" style="background-color:lightblue" type="submit">Submit Comment</button>
</form>
</div>
</div>
views.py
from django.shortcuts import render
from django.views import generic
from .forms import CommentForm
from .models import Comment
def add_comment_to_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('/blog/<int:pk>', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/post.html', {"form":form})
form = CommentForm(request.POST)
form = CommentForm()
In django's admin i can add new comments and the form loads as expected there but does not work on the blog post itself. Admin submitted comments through the admin panel are also saving and displaying fine.
you have a typo in forms.py
change models to model
from django import forms
from django.forms import ModelForm
from .models import Comment
from django.db import models
class CommentForm(forms.ModelForm):
class Meta:
model = Comment # changed from models
exclude = ['post']
in views.py
you are missing imports
from django.shortcuts import get_object_or_404,redirect
from .models import Post
other changes
in your models.py
the to string method for classes is __str__ not _str_
with this changes i was able to reproduce this django project with your snippets that works in posting comments