I'm having an issue with Python Django. It has to do with foreign keys and models. I have been told before that my questions are often incredibly mediocre, so please bear with me on this. I am trying to configure comments for a social network I'm working on and I've just got comments working, kind of. The issue is that, although I can input a comment and the database will log it and the person who wrote it, it won't log the post it is on. It always returns null. This is really the full extent of what I can say, as I REALLY don't understand what is happening. Here are a number of different code snippets and image that should hopefully be able to elaborate on the issue without requiring my interjection.
1:
The models of the post-app
https://pastebin.com/XXNsCa5g
The important model being:
class Comment(models.Model):
2:
The reply template:
https://pastebin.com/GsLUQqYp
3:
The reply view:
class PostReplyView(CreateView):
model = models.Comment
template_name = 'post_reply.html'
fields = ['comment']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
Finally, a visual representation of what is missing from a comment when it is posted:
enter image description here
Updated using normal view:
models.py
from django.db import models
from user.models import MyUser
from django.urls import reverse
# Create your models here.
class Post(models.Model):
user = models.ForeignKey(MyUser, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
content = models.TextField()
posted_on = models.DateTimeField(auto_now=True, auto_now_add=False)
updated_on = models.DateTimeField(auto_now=False, auto_now_add=True)
slug = models.SlugField(blank=True, null=True)
def __str__(self):
return "%s by %s" % (self.title, self.user.get_full_name())
def get_absolute_url(self):
return reverse('post:detail', kwargs={'slug':self.slug})
class Comment(models.Model):
author = models.ForeignKey(MyUser, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
comment = models.TextField()
posted_on = models.DateTimeField(auto_now_add=True, auto_now=False)
def __str__(self):
return "%s commented on %s" % (self.author, self.post)
forms.py
from django import forms
from .models import Post, Comment
class newPost(forms.ModelForm):
class Meta:
model = Post
fields = ['title','content']
class newComment(forms.ModelForm):
class Meta:
model = Comment
fields = ['comment']
views.py
def detail(request, slug=None):
post = get_object_or_404(Post, slug=slug)
user = request.user
if request.method == 'POST':
comment = newComment(request.POST)
if comment.is_valid():
new_Comment = comment.save(commit=False)
new_Comment.author = user
new_Comment.post = post
new_Comment.save()
# successfully commented, now do whatever you want
return HttpResponse('commented')
else:
comment = newComment()
context = {
'post' : post,
'comment' : comment
}
return render(request, 'post/detail.html', context)
detail.html
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<hr>
<form action="" method="post">
{% csrf_token %}
{{ comment.as_p }}
<input type="submit">
</form>
** you are getting empty field on "post" because you are not linking it with any post, but in the above example i have shown you how i have done it and how you can also do the same for your project **
Related
I want to add like unlike feature to my blog site, everythin is okay there, like and unlike objects are being created.. But I'm getting NoReverseMatch when I'm clicking the Like and Unlike..and the problem is I can't figure it out why I'm getting this...my models.py, views.py, urls.py, blog_page.html...all are attatched here..
plz try help me solve this
**models.py**
from email.policy import default
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Blog(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200, verbose_name="Put a Title")
blog_content = models.TextField(verbose_name="What is on your mind")
blog_image = models.ImageField(upload_to="blog_images", default = "/default.png")
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Comment(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_comment" )
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_comment")
comment = models.TextField()
comment_date = models.DateField(auto_now_add=True)
def __str__(self):
return self.comment
class Like(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_liked")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_liked")
class Unlike(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_unliked")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_unliked")
**views.py**
from django.shortcuts import render
from . models import Blog, Comment, Like, Unlike
# Create your views here.
def home(request):
blogs = Blog.objects.all()
context = {'blogs': blogs}
return render(request, 'blog_app/home.html', context)
def blog_view(request, pk):
blog = Blog.objects.get(id=pk)
context = {"blog": blog}
return render(request, 'blog_app/blog_page.html', context)
def like(request, pk):
blog = Blog.objects.get(id=pk)
user = request.user
liked, like = Like.objects.get_or_create(blog=blog, user=user)
context = {"liked" : liked}
return render(request, "blog_app/blog_page.html", context)
def unlike(request, pk):
blog = Blog.objects.get(id=pk)
user = request.user
unliked, unlike = Unlike.objects.get_or_create(blog=blog, user=user)
context = {"unliked" : unliked}
return render(request, "blog_app/blog_page.html", context)
**urls.py**
from django.urls import path
from blog_app import views
urlpatterns = [
path("", views.home, name='home'),
path("blog_page/<str:pk>/", views.blog_view, name='blog_page'),
path("like/<str:pk>/", views.like, name="like"),
path("unlike/<str:pk>/", views.unlike, name="unlike"),
]
**blog_page.html**
{% extends "main.html" %}
{% load static %}
{% block content %}
<div style="text-align:center;">
<h2>{{blog.title}}</h2>
<img src="{{blog.blog_image.url}}" alt="" width="630px" height="300px">
</div>
<div style="text-align:center;">
{{blog.blog_content|linebreaks}}
</div>
{% if liked %}
<h4>Unlike</h4>
{% else %}
<h4> Like </h4>
{% endif %}
{% endblock content %}
Your URLs are expecting a string value for blog_id but you are passing them an int in {% url 'unlike' blog.id %} Try changing your URL file to expect an int, and you should be able to look it up more successfully.
path("blog_page/<int:pk>/", views.blog_view, name='blog_page'),
path("like/<int:pk>/", views.like, name="like"),
path("unlike/<int:pk>/", views.unlike, name="unlike"),
Also, as you are using the same page template for the like and unlike view, you will need to pass the blog element in the context again to make links work on those pages, eg,
context = {"liked" : liked, "blog", blog}
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.
I am trying to make a contact form but it's html template does not see {{ form }} template. What am I doing wrong? Where is an error.
My code is attached above.
models.py
class Contact(models.Model):
listing = models.CharField(max_length=200)
listing_id = models.IntegerField()
name = models.CharField(max_length=200)
email = models.EmailField()
phone = models.CharField(max_length=100)
message = models.TextField(blank=True)
file = models.FileField(upload_to='files/%Y/%m/%d/', blank=True)
contact_date = models.DateTimeField(default=datetime.now, blank=True)
user_id = models.IntegerField(blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('listings', kwargs={'pk': self.pk})
In views.py file
class ContactCreate(CreateView):
model = Contact
form_class = ContactForm
template_name = 'listing.html'
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('listings/<int:pk>/', views.ContactCreate.as_view(), name='contact-create')
]
html
<form action="{% url 'contact-create' pk=listing.pk %}" method="post">
{{ form }}
{% csrf_token %}
<input type="submit" value="Send" class="btn btn-block btn-secondary">
</form>
forms.py
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ['name','email','phone','file']
Could you help me out, please
If you provide a form_class with ContactForm, Django is expecting a form to be provided so you have two options:
Create a form.py and add the following:
from django import forms
class ContactForm(forms.Form):
name = forms.CharField()
message = forms.CharField(widget=forms.Textarea)
Don't forget to add that to your view:
from myapp.forms import ContactForm
If you want your custom form to be display you have to specify the form_class in your create view:
form_class = ContactForm
If you are using a custom template to display your form add the following to your create view:
template_name = 'listing.html' # or the path to your template
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})
.
.
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 %}