Forigen Key not displaying in rendered model form - python

I am looking for guidance on where I am going wrong. My model form is rendering correctly however the author has no option to select or input. I suspect this is is because the author is a foreign key. How do I get around this so the form will display a list of users or allow to manually input a name. Any help would be greatly appreciated :)
models.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="workout_posts")
updated_on = models.DateTimeField(auto_now=True)
featured_image = CloudinaryField('image', default='placeholder')
content = models.TextField(default='SOME STRING')
excerpt = models.TextField(blank=True)
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
# ordered created on field starting with newest first
ordering = ['-created_on']
def __str__(self):
return self.title
forms.py
class MakeWorkOutForm(forms.ModelForm):
class Meta:
model = Post
fields = '__all__'
views.py
def createWorkOut(request):
form = MakeWorkOutForm
context = {'form': form}
return render(request, "add-workout.html", context)
html
{% extends "base.html" %} {% block content %} {% load static %}
<h1>Create A Workout</h1>
<form action="" method="POST">
{% csrf_token %}
{{form}}
<input type="submit" name="submit">
</form>
{% endblock content %}

Related

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 can I link a comment to its corresponding post in Django?

I am building a Django project where I have an index page that lists all posts. The user can click on the name of a post and this will take them to a detail page with the complete post information (date, content, category). This detail page also has a link that will take the user to a form where they can leave a comment. Once the user clicks submit they are supposed to navigate back to the post detail page and the comment is supposed to be there. The issue I am having right now is that the comment is being automatically assigned to the first post in the index list rather than the post the user had visited (I think this may have something to do with the current default setting in my models, but how else can I get the post id?). How can I make it so that the comment is assigned to its correct post? I have tried everything with the models and views but nothing seems to work. Thank you for your help, I think the solution to this might be simple but I can't find it anywhere.
Here is my relevant models:
class UserPost(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User, default=1,
on_delete = models.CASCADE
)
#id = models.AutoField(primary_key=True)
def __str__(self):
"""String for representing the UserPost object."""
return self.title
def get_absolute_url(self):
"""Returns the url to access a detail record for this user post."""
return reverse('userpost-detail', args=[str(self.id)])
class Comment(models.Model):
author = models.ForeignKey(User, default=1,
on_delete = models.CASCADE
)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
def comment_default():
return {UserPost.id}
post = models.ForeignKey(UserPost, default= comment_default, on_delete=models.CASCADE, related_name="comments")
def __str__(self):
"""String for representing the comment object."""
return '%s - %s - %s' % (self.post.title, self.author, self.created_on)
def get_absolute_url(self):
return reverse('userpost-detail', args=[str(self.post.id)])
And my views:
class UserPostDetailView(generic.DetailView):
model = UserPost
#post = UserPost.objects.get(id=id)
#comments = Comment.objects.filter(Comment.post)
def get_context_data(self, **kwargs):
context = super(UserPostDetailView, self).get_context_data(**kwargs)
context['Comment'] = UserPost.comments
return context
class PostCreate(CreateView):
model = UserPost
fields = ['title', 'category', 'content']
class CommentCreate(CreateView):
model = Comment
fields = ['post','content']
And my html:
{% extends "base.html" %}
{% block page_content %}
<h1>Title: {{ userpost.title }}</h1>
<p><strong>Author:</strong> {{ userpost.author }}</p>
<p><strong>Content:</strong> {{ userpost.content }}</p>
<p><strong>Category:</strong> {{ userpost.category }}</p>
<a class="btn btn-primary" href="{% url 'comment-create' %}" role="button">Leave a Comment</a>
<h3>Comments:</h3>
{% for comment in userpost.comments.all %}
<p>
On {{comment.created_on.date }}
<b>{{ comment.author }}</b> wrote:
</p>
<p>{{ comment.content }}</p>
<hr>
{% endfor %}
{% endblock %}
You need to pass Post ID in your url for this.
path("comment/<int:post_id>/", CommentCreateView, name="comment-create")
Now in template
<a class="btn btn-primary" href="{% url 'comment-create' userpost.id %}" role="button">Leave a Comment</a>
Views
class CommentCreateView(CreateView):
model = Comment
fields = ['content'] # remove field post here
def form_valid(self, form):
form.instance.post_id = self.kwargs.get("post_id")
return super().form_valid(form)

Upload image via ModelForm in django

When I try to submit my form it says "This field is required."
for an image even though I provide the image and other details to it.
forms.py file
from django.forms import ModelForm
from .models import Status
class CreatePost(ModelForm):
class Meta:
model=Status
fields = ["username","text","privacy","image"]
models.py file
class Status(models.Model):
title=models.CharField(max_length=20,default="updated status")
username = models.ForeignKey('User',on_delete=models.CASCADE)
#username = models.CharField(max_length=20)
text = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to="media/image",null=True)
time = models.DateTimeField(auto_now=True)
privacy = models.CharField(max_length=5, blank=True, null=True)
gid = models.IntegerField(blank=True, null=True)
dp = models.SmallIntegerField(blank=True, null=True)
class Meta:
#unique_together = (('username', 'dp'),)
#managed = False
db_table = 'status'
view.py
def create_post(request):
form=CreatePost(request.POST or None)
if request.method=="POST":
if form.is_valid():
instance=form.save(commit=False)
instance.time=time.time()
instance.save()
return redirect('post',)
return render(request,"uposts/createpost.html",{'form':form})
createpost.html
{% extends "friendsbook/structure.html" %}
{% block content %}
<form action="" method="post">
{%csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
{% endblock %}
What it said after clicking on save button
I am only taking 4 fields in form because all other fields can be null. For time field I took care of that in views.py by giving the time there.
You have to modify the template like this adding multipart/form-data:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="myfile">
<button type="submit">Upload</button>
</form>
and in views.py, you can access the uploaded file using request.FILES.

Creating Polls app form Django

Trying to create a form for my polls app.But I am not able to include choices as well for it.I can only add polls right now through admin.
(Its the official django polls app tutorial and i am trying to extend it further by adding a form)
Models.py
class Question(models.Model):
question_text = models.CharField(max_length=200)
publish_date = models.DateTimeField('date published',null=True,blank=True)
def __str__(self):
return self.question_text
def get_absolute_url(self):
return reverse('polls:index')
class Choice(models.Model):
question_text = models.ForeignKey(Question,on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
forms.py
class QuestionForm(forms.ModelForm):
question_text = forms.CharField(required=True)
publish_date = forms.CharField(required=False)
choice_text = forms.CharField(required=True)
class Meta():
model = Question
fields = ('question_text','choice_text')
View To create Poll
class CreatePoll(CreateView):
redirect_field_name = 'polls/index.html'
template_name = 'polls/poll_form.html'
form_class = QuestionForm
model = Question
This is My Form View But the choice entered doesnt get saved.Saw in the admin view too
polls_form.html
{% extends 'polls/base.html' %}
{% block content %}
<h1>New Post</h1>
<form class="post-form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<button type="submit" class="save btn btn-primary">Save</button>
</form>
<script>var editor = new MediumEditor('.editable');</script>
{% endblock %}

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