I'm making an answering/commenting system for my post's. And here's how the models.py looks:
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.utils import timezone
import misaka
from groups.models import Group
from django.contrib.auth import get_user_model
User = get_user_model()
class Post(models.Model):
user = models.ForeignKey(User, related_name="posts")
created_at = models.DateTimeField(auto_now=True)
message = models.TextField()
message_html = models.TextField(editable=False)
group = models.ForeignKey(Group, related_name="posts",null=True, blank=True)
def __str__(self):
return self.message
def save(self, *args, **kwargs):
self.message_html = misaka.html(self.message)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse(
"posts:single",
kwargs={
"username": self.user.username,
"pk": self.pk
}
)
class Meta:
ordering = ["-created_at"]
unique_together = ["user", "message"]
class Answer(models.Model):
post = models.ForeignKey('posts.Post', related_name='posts')
author = models.ForeignKey(User, related_name='answers')
answer = models.TextField()
create_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.answer
def get_absolute_url(self):
return reverse('post_detail', kwargs={
"username": self.user.username,
"pk": self.pk,
})
I've been having a problem, with basically showing the answers/comment's in the post detail. Here's how my post detail looks:
<!DOCTYPE html>
{%load staticfiles%}
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="keywords" content="footer, address, phone, icons" />
<link href="https://fonts.googleapis.com/css?family=Abel|Raleway|Signika|Signika+Negative" rel="stylesheet">
<title>Ask Uptown</title>
<style media="screen">
.logo-text span{
color: #5383d3;
}
.backgr{
background-color: #7F7F7F;
height: 13vh;
width: 100%;
background-size: cover;
background-position: center;
}
header{
background: src(.backgr);
}
.no-ans{
position: relative;
top: 50px;
left: 50px;
font-size: 20px;
}
.add-comment{
position: relative;
text-decoration: none;
z-index: 99;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 40px;
background: linear-gradient(45deg, #B388EB, #8093F1);
border-radius: 20px;
color: #FFF;
font-size: 20px;
letter-spacing: 1px;
font-weight: 200;
left: 1100px;
text-decoration: none;
left: 800px;
top: 75px;
}
</style>
</head>
<body>
<header>
<div class="backgr">
<nav class="" role="navigation" id="navbar">
<div class="">
<div class="logo">
<a class="logo-text" href="{% url 'home' %}"><h3>Uptown<span>Ask</h3></span></a>
</div>
<ul class="main-nav">
{% if user.is_authenticated %}
<li class="active">Home</li>
<li>Stuck? Ask A question</li>
<li>Groups</li>
<li>Contact</li>
<li>Log out</li>
{% else %}
<li class="active">Home</li>
<li>Groups</li>
<li><a href="{% url 'accounts:login' %}" >Log in</a></li>
<li><a href="{% url 'accounts:signup' %}" >Sign up</a></li>
<li>Contact</li>
{% endif %}
</ul>
</header>
<section>
{% block post_content %}
<div class="col-md-8">
{% include "posts/_post.html" %}
</div>
{% endblock %}
<a class="add-comment" href="{% url 'posts:add_comment_to_post' pk=post.pk%}">Answer This Question</a>
{% for comment in post.comments.all %}
<br>
{% if user.is_authenticated %}
{{ comment.created_date }}
{% if not comment.approved_comment %}
<a class="btn btn-default" href="{% url 'comment_remove' pk=comment.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-default" href="{% url 'comment_approve' pk=comment.pk %}"><span class="glyphicon glyphicon-ok"></span></a>
{% endif %}
<p>{{ comment.text|safe|linebreaks }}</p>
<p>Posted by: <strong>{{ comment.author }}</strong></p>
{% endif %}
{% empty %}
<p class="no-ans">No Answer's posted.</p>
{% endfor %}
</div>
</section>
<footer class="footer-distributed">
<div class="footer-left">
<h3>Uptown<span>Ask</span></h3>
<p class="footer-links">
Home
·
Blog
·
About
·
Contact
</p>
<p class="footer-company-name">Ask Uptown © 2017</p>
</div>
<div class="footer-center">
<div class="adress-sec">
<p class="p-adress">Address: Tripoli Street, Algeria Road, Mirdif Area - Dubai, United Arab Emirtes</p>
</div>
<div class="phone-sec">
<p>Phone: 04 251 5001</p>
</div>
<div class="email-sec">
<p class="p-email">Email: Uptownschool#gmail.com</p>
</div>
</div>
<div class="footer-right">
<p class="footer-company-about">
<span>About the company</span>
Lorem ipsum dolor sit amet, consectateur adispicing elit. Fusce euismod convallis velit, eu auctor lacus vehicula sit amet.
</p>
<div class="icons">
<img src="images/twitter.png" alt="Twitter" class="twitter" >
<img src="facebook.png" alt="Facebook" class="facebook" >
<img src="insta.png" alt="Instagram" class="instagram" >
</div>
</div>
</footer>
</body>
</html>
Here's an image of how it looks on the actual site. PIcture of how the post detail looks on the actual site
but I'm having a problem showing the comment's/answer's when they are posted. If I use the admin to post it doesn't show. and if I click on the answer this question button it gives me this error: Picture for error
Here are my views and urls.py:
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.urlresolvers import reverse_lazy
from django.http import Http404
from django.views import generic
from braces.views import SelectRelatedMixin
from . import forms
from . import models
from django.contrib.auth import get_user_model
User = get_user_model()
class PostList(SelectRelatedMixin, generic.ListView):
model = models.Post
select_related = ("user", "group")
class UserPosts(generic.ListView):
model = models.Post
template_name = "posts/user_post_list.html"
def get_queryset(self):
try:
self.post_user = User.objects.prefetch_related("posts").get(
username__iexact=self.kwargs.get("username")
)
except User.DoesNotExist:
raise Http404
else:
return self.post_user.posts.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["post_user"] = self.post_user
return context
class PostDetail(SelectRelatedMixin, generic.DetailView):
model = models.Post
select_related = ("user", "group")
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(
user__username__iexact=self.kwargs.get("username")
)
class CreatePost(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
# form_class = forms.PostForm
fields = ('message','group')
model = models.Post
# def get_form_kwargs(self):
# kwargs = super().get_form_kwargs()
# kwargs.update({"user": self.request.user})
# return kwargs
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class DeletePost(LoginRequiredMixin, SelectRelatedMixin, generic.DeleteView):
model = models.Post
select_related = ("user", "group")
success_url = reverse_lazy("posts:all")
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id=self.request.user.id)
def delete(self, *args, **kwargs):
messages.success(self.request, "Post Deleted")
return super().delete(*args, **kwargs)
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('post_detail', pk=post.pk)
else:
form = forms.CommentForm()
return render(request, 'posts/comment_form.html', {'form': form})
def comment_remove(request, pk):
comment = get_object_or_404(Comment, pk=pk)
post_pk = comment.post.pk
comment.delete()
return redirect('post_detail', pk=post_pk)
The comment_remove function based view is for users to delete their comment/answer. and the add_comment_to_post is the class that posts the comment/answer.
from django.conf.urls import url
from . import views
app_name='posts'
urlpatterns = [
url(r"^$", views.PostList.as_view(), name="all"),
url(r"new/$", views.CreatePost.as_view(), name="create"),
url(r"by/(?P<username>[-\w]+)/$",views.UserPosts.as_view(),name="for_user"),
url(r"by/(?P<username>[-\w]+)/(?P<pk>\d+)/$",views.PostDetail.as_view(),name="single"),
url(r"delete/(?P<pk>\d+)/$",views.DeletePost.as_view(),name="delete"),
url(r'^post/(?P<pk>\d+)/comment/$', views.add_comment_to_post, name='add_comment_to_post'),
url(r'^comment/(?P<pk>\d+)/remove/$', views.comment_remove, name='comment_remove'),
]
I'cant seem to find a way to show the comment's under the post detail, plzz help if your a django genius.
Change:
post = models.ForeignKey('posts.Post', related_name='posts')
To
post = models.ForeignKey('posts.Post', related_name='comments')
So that your template’s ‘post.comments.all’ works
Related
I have two models with OneToMany relation between them. personelModel and arizaModel. When I click the save button, I get the following error:
"IntegrityError at / NOT NULL constraint failed: kullanici_arizamodel.p_id_id"
personelModel saved but arizaModel not saved in database table. I want both models to be saved in database
I want help.
/my english is not good i am sorry about that/
models.py:
from email.policy import default
from tabnanny import verbose
from django.db import models
# Create your models here.
class personelModel(models.Model):
p_sicil = models.CharField(max_length=8, verbose_name='Personel Sicili')
p_isim = models.CharField(max_length=50, verbose_name='Personel Adı')
p_bilgisayar_adi = models.CharField(max_length=4, verbose_name='Bilgisayar Adı')
p_durum = models.BooleanField(default=True, verbose_name='Personel Durumu')
class Meta:
verbose_name = "Personel"
verbose_name_plural = "Personeller"
def __str__(self):
return self.p_sicil
class arizaModel(models.Model):
p_id = models.ForeignKey(personelModel, on_delete=models.CASCADE)
a_aciklama = models.CharField(max_length=100, verbose_name='Arıza Açıklama')
a_acilma_tarihi = models.DateTimeField(auto_now_add=True, verbose_name='Açılma Tarihi')
a_durum = models.BooleanField(default=True, verbose_name='Arıza Durumu')
a_kapanma_tarihi = models.DateTimeField(auto_now_add=True, verbose_name='Kapanma Tarihi')
class Meta:
verbose_name = "Arıza"
verbose_name_plural = "Arızalar"
def __str__(self):
return self.a_aciklama
views.py
from django.shortcuts import render
from django.urls import reverse_lazy
from kullanici.forms import PersonelBilgileriForm, ArizaBilgileriForm
def kullaniciArizaKaydetView(request):
form1 = PersonelBilgileriForm(request.POST, prefix='personel_bilgileri')
form2 = ArizaBilgileriForm(request.POST, prefix='ariza_bilgileri')
if request.method == 'POST':
if form1.is_valid() and form2.is_valid():
personel_bilgileri = form1.save()
ariza_bilgileri = form2.save()
return render(request, 'kullanici.html',{'PersonelBilgileriForm': form1, 'ArizaBilgileriForm': form2})
forms.py
from django import forms
from . models import personelModel, arizaModel
class PersonelBilgileriForm(forms.ModelForm):
p_sicil = forms.CharField(widget=forms.TextInput(attrs={
'class' : 'form-control',
'placeholder' : 'ab sicil',
'maxlength' : '8'
}))
p_isim = forms.CharField(widget=forms.TextInput(attrs={
'class' : 'form-control',
'placeholder' : 'Adınız Soyadınız',
'maxlength' : '50'
}))
p_bilgisayar_adi = forms.CharField(widget=forms.TextInput(attrs={
'class' : 'form-control',
'placeholder' : 'Bilgisayar adınızın son 4 hanesi',
'maxlength' : '4'
}))
class Meta:
model = personelModel
fields = ['p_sicil','p_isim','p_bilgisayar_adi']
class ArizaBilgileriForm(forms.ModelForm):
a_aciklama = forms.CharField(widget=forms.Textarea(attrs={
'class' : 'form-control',
'placeholder' : 'Arızayı yazınız'
}))
class Meta:
model = arizaModel
fields = ['a_aciklama']
kullanici.html
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="author" content="esli">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Arıza Kayıt Giriş Ekranı</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
</head>
<body class="bg-dark">
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-md-4 mt-5 bg-light rounded">
<h3 class="text-center fw-bold pt-3">ARIZA BİLDİRİM MERKEZİ</h3>
<p class="text-center lead">
Karşılaştığınız sorunu detaylı olarak açıklayınız
</p>
<hr class="bg-light">
{% if messages %}
{% for m in messages %}
<div class="border bg-success text-white">
<h5 class="text-center pt-2">{{m}}</h5>
</div>
{% endfor %}
{% endif %}
<form action="" method="POST" id="form-box" class="p-2">
{% csrf_token %}
<div class="form-group input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-user"></i></span>
</div>
{{PersonelBilgileriForm.p_sicil}}
</div>
<div class="form-group input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-user"></i></span>
</div>
{{PersonelBilgileriForm.p_isim}}
</div>
<div class="form-group input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-desktop"></i></span>
</div>
{{PersonelBilgileriForm.p_bilgisayar_adi}}
</div>
<div class="form-group input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-comment-alt"></i></span>
</div>
{{ArizaBilgileriForm.a_aciklama}}
</div>
<div class="form-group">
<input type="submit" name="submit" id="submit" class="btn btn-primary btn-block" value="GÖNDER">
</div>
</form>
</div>
</div>
</div>
</body>
</html>
I was expecting it to register in the database table in its data from both models but it didn't
p_id = models.ForeignKey(personelModel, on_delete=models.CASCADE)
# p_id is null when save form you must be pass personelModel instance at saving time of
form2 = ArizaBilgileriForm(request.POST, prefix='ariza_bilgileri')
-------- Hint ------
if request.method == 'POST':
if form1.is_valid() and form2.is_valid():
personel_bilgileri = form1.save()
ariza_bilgileri = form2.save(commit=False)
ariza_bilgileri.p_id == personelModel.objects.get(id=1) # foreign key instance must be pass
ariza_bilgileri.save() # then after save form
NOTE:- in your case (ariza_bilgileri = form2.save()) not get value of p_id so it's throw error
I am learning Python and Django, and I am trying to create a recipe with a form. The problem is I have two models, Recipe and RecipeIngredient and I don't know how to add recipe ingredients to the form since it requires the primary key of the recipe and from what I understand, the key is not created until after the form is saved? So how can I create a recipe with both the Recipe and RecipeIngredient when Recipe is not yet initialized?
Models.py:
class Recipe(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
image = models.ImageField(upload_to='image/', blank=True, null=True)
name = models.CharField(max_length=220) # Lasanga
description = models.TextField(blank=True, null=True)
notes = models.TextField(blank=True, null=True)
cookTime = models.CharField(max_length=50, blank=True, null=True)
timeStamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
#property
def title(self):
return self.name
def get_absolute_url(self):
return reverse("recipes:detail", kwargs={"id": self.id}) # recipes is from url.py app_name
def get_hx_url(self):
return reverse("recipes:hx-detail", kwargs={"id": self.id}) # recipes is from url.py app_name
def get_edit_url(self):
return reverse("recipes:update", kwargs={"id": self.id})
def get_image_upload_url(self):
return reverse("recipes:recipe-ingredient-image-upload", kwargs={"parent_id": self.id})
def get_delete_url(self):
return reverse("recipes:delete", kwargs={"id": self.id})
def get_ingredients_children(self):
return self.recipeingredient_set.all()
def get_instruction_children(self):
return self.recipeinstruction_set.all()
class RecipeIngredient(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
name = models.CharField(max_length=220) # grilled chicken pasta
description = models.TextField(blank=True, null=True)
quantity = models.CharField(max_length=50, blank=True, null=True)
unit = models.CharField(max_length=50, validators=[validate_unit_of_measure], blank=True, null=True)
instructions = models.TextField(blank=True, null=True)
timeStamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
def get_absolute_url(self):
return self.recipe.get_absolute_url() # recipe cannot be none
def get_hx_edit_url(self):
kwargs = {
"parent_id": self.recipe.id,
"id": self.id
}
return reverse("recipes:hx-ingredient-detail", kwargs=kwargs)
def get_delete_url(self):
kwargs = {
"parent_id": self.recipe.id,
"id": self.id
}
return reverse("recipes:ingredient-delete", kwargs=kwargs)
Views.py
#login_required
def recipe_create_view(request):
form = RecipeForm(request.POST or None)
context = {
"form": form,
}
if form.is_valid():
obj = form.save(commit=False)
obj.user = request.user
obj.save()
if request.htmx: # necessary to pass headers from htmx response if we want the django to recognise the htmx change
headers = {
"HX-Redirect": obj.get_absolute_url()
}
return HttpResponse("Created", headers=headers)
# if request.htmx: # could use this but the url doesn't update, stays as create, would need to use HX-Push header & HttpResponse + context somehow
# context = {
# "object": obj
# }
# return render(request, "recipes/partials/detail.html", context)
return redirect(obj.get_absolute_url())
return render(request, "recipes/create.html", context)
#login_required
def recipe_ingredient_update_hx_view(request, parent_id=None, id=None): # this is both create & edit, can create
if not request.htmx:
raise Http404
try:
parent_obj = Recipe.objects.get(id=parent_id, user=request.user)
except:
parent_obj = None
if parent_obj is None:
return HttpResponse("Not Found.")
instance = None
if id is not None:
try:
instance = RecipeIngredient.objects.get(recipe=parent_obj, id=id) # think of this as an object if that helps
except:
instance = None
form = RecipeIngredientForm(request.POST or None, instance=instance)
url = reverse("recipes:hx-ingredient-create", kwargs={"parent_id": parent_obj.id})
if instance:
url = instance.get_hx_edit_url()
context = {
"url": url,
"form": form,
"object": instance
}
if form.is_valid():
new_obj = form.save(commit=False)
if instance is None:
new_obj.recipe = parent_obj
new_obj.save()
context['object'] = new_obj # because it's possible the object/instance in None
return render(request, "recipes/partials/ingredient-inline.html", context)
return render(request, "recipes/partials/ingredient-form.html", context)
forms.py
from django import forms
from .models import Recipe, RecipeIngredient
class RecipeForm(forms.ModelForm):
class Meta:
model = Recipe
fields = ['name', 'image', 'description', 'notes', 'cookTime']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields:
new_data = {
"placeholder": f"Recipe {str(field)}",
"class": "form-control",
}
self.fields[str(field)].widget.attrs.update(new_data)
class RecipeIngredientForm(forms.ModelForm):
class Meta:
model = RecipeIngredient
fields = ['name', 'quantity', 'unit']
urls.py
from django.urls import path
from .views import (
recipe_list_view,
recipe_delete_view,
recipe_create_view,
recipe_update_view,
recipe_detail_hx_view,
recipe_ingredient_update_hx_view,
recipe_ingredient_delete_view,
recipe_ingredient_image_upload_view,
recipe_ingredient_url_scrape_view
)
app_name='recipes' # allows use of recipes:list as a reverse url call
urlpatterns = [
path('', recipe_list_view, name='list'), # index / home / root
path('create/>', recipe_create_view, name='create'),
path('hx/<int:parent_id>/ingredient/<int:id>', recipe_ingredient_update_hx_view, name='hx-ingredient-detail'), #or detail
path('hx/<int:parent_id>/ingredient/', recipe_ingredient_update_hx_view, name='hx-ingredient-create'),
]
create.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load static %}
{% block content %}
<div class="container-fluid px-5">
<h1 class="pb-5">Create Recipe</h1>
<div id="recipe-container">
<form action='.' method="POST" hx-post='.'>
{% csrf_token %}
<div class='row'>
<div class="row d-flex pb-5">
<div class="col-12 col-lg-6 justify-content-center d-flex order-first order-lg-last pictureBox"
style="height: 400px; width:450; border: solid tomato 1px;">
<div class="align-self-center">
{{ form.image|as_crispy_field }}
</div>
</div>
<div class="col-12 col-lg-6 order-lg-first">
<div class="pb-3">{{ form.name|as_crispy_field }}</div>
<div class="pb-3">{{ form.description|as_crispy_field }}</div>
</div>
</div>
<div class="col-12 col-md-6">
{{ form.notes|as_crispy_field }}
</div>
<div class="col-12 col-md-6">
{{ form.cookTime |as_crispy_field }}
</div>
</div>
</div>
<div class='col-12 col-md-4'>
<!-- ADD INGREDIENTS ? -->
</div>
<div class="htmx-indicator">Loading...</div>
<div class="d-flex">
<button class="btn btn-success htmx-inverted-indicator" style='margin-top:10px;' type='submit'>Save</button>
<a class="btn btn-danger" href='{% url "recipes:list" %}'>Delete</a>
</div>
{% if message %}
<p>{{ message }}</p>
{% endif %}
</form>
</div>
</div>
{% endblock content %}
ingredient-form.html
<form action='.' method="POST" hx-post='{% if url %} {{ url }} {% else %} . {{% endif %}' hx-swap='outerHTML'>
{% csrf_token %}
{{ form.as_p}}
<div class="htmx-indicator">Loading...</div>
<button class="htmx-inverted-indicator" style='margin-top:10px;' type='submit' >Save</button>
</form>
ingredient-inline.html
<div class="py-1" id="ingredient-{{object.id}}">
<p>{% if not edit %} <b>{{ object.quantity }} {% if object.unit %} {{ object.unit }} {% endif %}</b> {% else %} {{ object.quantity }} {{ object.unit }} {% endif %} - {{ object.name }}</p>
{% if edit %}
<button class="btn btn-primary" hx-trigger='click' hx-get='{{ object.get_hx_edit_url }}' hx-target="#ingredient-{{object.id}}">Edit</button> <!-- target will replace whole div-->
<button class="btn btn-danger" href='{{ object.get_delete_url }}' hx-post='{{ object.get_delete_url }}' hx-confirm="Are you sure you want to delete {{ object.name }}?" hx-trigger='click' hx-target="#ingredient-{{object.id}}" hx-swap="outerHTML">Delete</button>
{% endif %}
</div>
The key to this problem is using a formset, as you will likely want to save multiple ingredients to the recipe. Django documentation outlines how to use them. Your view would end up looking something like below, allowing you to save the parent model, which will give you the parent instance/primary key to then save the ingredients.
def recipe_create_view(request):
form = RecipeForm(request.POST or None)
RecipeIngredientFormset = formset_factory(RecipeIngredientForm)
formset = RecipeIngredientFormset(request.POST or None)
context = {
"form": form,
"formset": formset,
}
if request.method == "POST":
if form.is_valid() and formset.is_valid():
parent = form.save(commit=False)
parent.user = request.user
parent.save()
#recipe ingredients
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
** urls.py file **
from django.urls import path
from main import views
app_name = 'main'
urlpatterns = [
path('', views.home, name='home'),
path('submit/', views.submit, name='submit'),
path('error-log/', views.error_log, name='error_log'),
]
** views.py file **
from django.shortcuts import render, get_object_or_404, redirect
import socket
from main.models import Paragraphs, Store_user_para
from main.forms import Store_user_para_forms
import random
global paragraph
def home(request):
''' to get the ip of user'''
hostname = socket.gethostname()
ip_address = socket.gethostbyname(hostname)
'''code to pass the pre defined paragraphs to the user '''
paragraphs = Paragraphs.objects.filter(active=True)
''' code to generate random paragraph '''
len_paragraphs = len(paragraphs)
number = random.randint(1, len_paragraphs-1)
paragraph = get_object_or_404(Paragraphs, id=number)
form = Store_user_para_forms()
return render(request, 'main/home.html', {'ip_address':ip_address, 'paragraph':paragraph, 'form':form})
def submit(request):
if request.method == "POST":
try:
global paragraph
form = Store_user_para_forms(request.POST)
data = form.save(commit=False)
data.paragraph_Id = request.POST.get('hidden_value', '')
data.user = request.user
data.save()
return redirect('main:submit')
except (ValueError):
form = Store_user_para_forms(request.POST)
print(form)
return render(request, 'main/submit.html', {'error':'Bad data passed in. Try again.'})
else:
data = Store_user_para.objects.filter()
return render(request, 'main/submit.html', {'data':data})
def error_log(request ):
return render(request, 'main/error_log.html')
** model.py file **
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Paragraphs(models.Model):
''' this class will store the pre defined paragraphs in backend '''
objects = models.Manager()
paragraph = models.TextField(blank=False, null=False)
created = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
class Meta:
verbose_name = 'Paragraph'
verbose_name_plural = 'Paragraphs'
def __str__(self):
return self.paragraph.split()[0]+ ' ' + self.paragraph.split()[1] + '...'
class Store_user_para(models.Model):
''' this class will store the users entered paragraph '''
objects = models.Manager()
paragraph_Id = models.ForeignKey('Paragraphs', on_delete=models.SET_NULL, null=True)
user_paragraph = models.TextField(null=False, blank=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
submitted = models.DateTimeField(auto_now_add=True)
Errors = models.IntegerField(null=True)
def __str__(self):
return self.user.username
** form.py file **
from django import forms
from main.models import Store_user_para
class Store_user_para_forms(forms.ModelForm):
class Meta:
model = Store_user_para
''' field to display on form '''
fields = [ 'user_paragraph']
** Home.html file , when I hit the submit button, I want not only to pass the user written pargraph but also the stored paragraph id to the store_user_para model **
{% extends 'main/base.html' %}
{% load static %}
{% block title %} | Home | {% endblock %}
{% block content %}
<form action="{% url 'main:submit' %}" method="POST">
{% csrf_token %}
<div class="unselectable" style="margin: 50px; margin-bottom: 20px;">
<div style="border: .1em solid green;">
<div style="font-size:20px; padding: 20px;">
<!-- this will bring the paragraphs from backend -->
{{ paragraph.paragraph }}
<input type="hidden" name='hidden_value' value="{{ paragraph.paragraph }}" >
</div>
</div>
</div>
<div style="margin: 50px; margin-top:15px ;">
<label for="id_user_paragraph"> </label>
<textarea name="user_paragraph" cols="40" rows="12" required="" id="id_user_paragraph"
placeholder="Start writing here" style="width: 100%; height:300px; font-size: 20px; padding: 5px; border: solid green 1px; "></textarea>
<button id="submit" type="submit" style="display: none;">Complete</button>
</div>
</form>
<div class="text-center">
<p class="btn btn-info disabled">Your IP: {{ ip_address }}</p>
</div>
<div class="row">
<div class="col-12 col-md-6 col-lg-6 col-sm-6 ">
<form action="">
<div class="text-right">
<button type="button" style="-ms-text-underline-position: none;" class="btn btn-outline-success" onclick="$('#submit').click()">
submit and check
</button>
</div>
</form>
</div>
<div class="col-12 col-md-6 col-lg-6 col-sm-6 ">
<div class="text-left">
<a href="{% url 'main:error_log' %}" style="-ms-text-underline-position: none;" class="btn btn-outline-danger mr-3">
view error log
</a>
</div>
</div>
</div>
<div style="margin-left: 10px; margin-top: 10px;">
<h4>work and payment details </h4>
</div>
<div style="margin-top: 10px; margin-left: 10px; margin-bottom: 50px;">
<h6>Target : n Paragraphs</h6>
<h6>Time : 00:00 - 00:00 </h6>
</div>
{% endblock %}
** this is the output in backend **
image of admin site
**how to submit the pre defined pargraph here **
you need to add the id to the fields list in forms.py
fields = ('id', 'user_paragraph')
then you can return it the same way as the paragraph
i want to pass the listview of post model and detailview of movies model in the same template using class based views
views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.urls import reverse
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, TemplateView
from .models import Post, Movies
from django.contrib.auth.models import User
class AboutView(TemplateView):
template_name = 'blog/about.html'
class MoviesListView(ListView):
model = Movies
template_name = 'blog/home_movies.html'
ordering = ['-date_released']
context_object_name = 'movies'
paginate_by = 10
class MoviesDetailListView(ListView):
template_name = 'blog/post_list.html'
context_object_name = 'posts'
paginate_by = 10
def get_queryset(self):
user = get_object_or_404(Movies, name=self.kwargs.get('name'))
return Post.objects.filter(name=user).order_by('-date_posted')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
movie = get_object_or_404(Movies, pk=self.kwargs.get('pk'))
context["movie"] = movie
class UserPostListView(ListView):
model = Post
template_name = 'blog/user_post.html' # app/model_viewtype.html
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 10
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
class PostDetailView(DetailView):
model = Post
context_object_name = 'posts'
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
context_object_name = 'posts'
fields = ['title', 'content', 'name']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
template_name = 'blog/user_post_update.html'
fields = ['title', 'content', 'name']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def get_success_url(self, **kwargs):
# obj = form.instance or self.object
return reverse("movies-detail", kwargs={'name': self.object.name, 'id': self.object.id})
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
def get_success_url(self, **kwargs):
# obj = form.instance or self.object
return reverse("movies-detail", kwargs={'name': self.object.name, 'id': self.object.id})
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
want to print detailview of model Movies from pk of movies passed in urls
i passed the movies name and pk from url but cant get other detail like in detailview we get from pk
urls.py
urlpatterns = [
path('about/', AboutView.as_view(), name='blog-about'),
path('user/<str:username>/', UserPostListView.as_view(), name='user-post'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/<str:name>/<int:id>/', PostCreateView.as_view(), name='post-create'),
path('', MoviesListView.as_view(), name='blog-home'),
path('<str:name>/<int:pk>/',MoviesDetailListView.as_view(), name='movies-detail'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
models.py
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from PIL import Image
class Movies(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
producer = models.CharField(max_length=100)
director = models.CharField(max_length=100)
date_released = models.DateTimeField(default=timezone.now)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
class Meta:
verbose_name_plural = "Movies"
def __str__(self):
return self.name
def get_id():
return
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.ForeignKey(Movies, on_delete=models.CASCADE,default=1)
def __str__(self):
return self.title
# return reverse('post-detail' , kwargs={'pk':self.pk})
def get_absolute_url(self):
return reverse('blog-home')
post_list.html
here i want to shoe the detail of movie and the post detail
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="keywords" content="footer, address, phone, icons" />
<meta name='viewport' content='width=device-width, initial-scale=1'>
<script src='https://kit.fontawesome.com/a076d05399.js'></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
<link href="http://fonts.googleapis.com/css?family=Cookie" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand mr-4" href="{% url 'blog-home' %}"><p style="font: normal 36px 'Cookie', cursive;margin:0px;">Axon <span style="color:#5383d3;">Blog</span></p></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{% url 'blog-home' %}"><i class="fa fa-fw fa-home" style="font-size:18px;"></i> Home</a>
<a class="nav-item nav-link" href="{% url 'blog-about' %}"><img src="https://img.icons8.com/ios/20/000000/about.png"/> About</a>
</div>
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if user.is_authenticated %}
<a class="nav-item nav-link" href="{% url 'profile' %}"><i class="fas fa-user-alt" style="font-size:18px;"></i> {{ user.username }}</a>
<a class="nav-item nav-link" href="{% url 'logout' %}"><i class="fa fa-fw fa-sign-out" style="font-size:16px;"></i> Logout</a>
{% else %}
<a class="nav-item nav-link" href="{% url 'login' %}"><i class="fas fa-sign-in-alt" ></i> Login</a>
<a class="nav-item nav-link" href="{% url 'register' %}"><i class="fas fa-user-plus" style="font-size:14px;"></i> Register</a>
{% endif %}
</div>
</div>
</div>
</nav>
</header>
</body>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<h1 class="mb-3">Reviews of {{ view.kwargs.name }} ({{ page_obj.paginator.count }})</h1>
<button class="btn"><i class="fa fa-plus"></i> Add Review</button>
<br><br>
{{ object.post_set.all }}
{% for post in posts %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-post' post.author.username %}">{{ post.author }}</a>
<small class="text-muted">{{ post.date_posted|date:"F d, Y " }}</small>
</div>
<h3><a class="article-title">{{ post.name }}</a></h3>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class ="btn btn-outline-info mb-4" href="?page=1">First</a>
<a class ="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class ="btn btn-info mb-4" href="?page={{ num }}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class ="btn btn-outline-info mb-4" href="?page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a class ="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}">Next</a>
<a class ="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}
</style>
</html>
Add the model details in context so you have them available at your template like:
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
movie = get_object_or_404(Movies, pk=self.kwargs.get('pk'))
context["movie"] = movie
Hello I'm a new comer to Django. I'm confused now having the thought of how django admin panel deleting option works and how to use that option in my site.The purpose is to use all CRUD options in one template not just with url like deleting one by one.
I have a models.py:
GRADES = (
('1', '1',), ('2', '2',),
('3', '3',), ('4', '4',),
('5', '5',), ('6', '6',),
('7', '7',), ('8', '8',),
('9', '9',), ('10', '10',),
('11', '11',),
)
class Grade(models.Model):
grade = models.CharField(null=True, max_length=200,
choices=GRADES, unique=True)
def __str__(self):
return self.grade
class Unique_grade(models.Model):
grades = models.ForeignKey(
Grade,
null=True, on_delete=models.SET_NULL,
verbose_name="Sinf raqamini kiriting",
)
A_B_C = models.CharField(max_length=1, null=True,)
motto = models.TextField(max_length=200, null=True,
verbose_name='Shior', blank=True,
unique=True, default=None)
class Meta:
unique_together = ['grades', 'A_B_C']
def clean_motto(self):
if self.cleaned_data['motto'] == "":
return None
else:
return self.cleaned_data['motto']
def __str__(self):
return f"{self.grades}-{self.A_B_C}"
class Pupil(models.Model):
first_name = models.CharField(max_length=200, null=True)
surname = models.CharField(max_length=200, null=True)
date_of_birth = models.DateField(
null=True)
nation = models.CharField(
max_length=100, null=True, verbose_name="Nation")
grade = models.ForeignKey(Unique_grade, null=True,
on_delete=models.SET_NULL)
m_full_name = models.CharField(
max_length=200, null=True, verbose_name="Mother's full name")
f_full_name = models.CharField(
max_length=200, null=True, verbose_name="Father's full name")
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = [
['first_name', 'date_of_birth',
'surname', 'nation',
'grade', 'm_full_name',
'f_full_name'],
]
def __str__(self):
return f"{self.first_name} {self.surname}."
my forms.py:
class CreateUniqueGrade(ModelForm):
class Meta:
model = Unique_grade
fields = "__all__"
error_messages = {
NON_FIELD_ERRORS: {
'unique_together': "Bunday sinf mavjud!",
},
}
def clean_motto(self):
if self.cleaned_data['motto'] == "":
return None
else:
return self.cleaned_data['motto']
my views.py:
from .models import *
from .forms import CreateUniqueGrade
from datetime import date
current_year = date.today().year
grade_nums = Grade.objects.all()
unique_grades = Unique_grade.objects.all()
def home(request):
content = {'grades': grade_nums, 'unique_grades': unique_grades,
'current_year': current_year}
return render(request, 'accounts/dashboard.html/', content)
def grades(request, g):
# grades = Grade.objects.all()
cform = CreateUniqueGrade()
if request.method == "POST":
cform = CreateUniqueGrade(request.POST)
if cform.is_valid():
cform.save()
return redirect(f'/grades/{g}')
uni = Unique_grade.objects.all().get(id=g)
unique_grade = Unique_grade.objects.all()
content = {
'grade': unique_grade.filter(grades=g),
'grades': grade_nums,
'unique_grades': unique_grades,
'current_year': current_year,
'g': g,
'Unique': cform,
}
return render(request, 'accounts/grades.html/', content)
def pupils(request, g, p):
pupil = Pupil.objects.all()
content = {
'pupil': pupil.filter(grade_id=p),
'grades': grade_nums,
'unique_grades': unique_grades,
'current_year': current_year
}
return render(request, 'accounts/pupils.html/', content)
def about(request):
return render(request, 'accounts/about.html/', {'grades': grade_nums, 'unique_grades': unique_grades, 'current_year': current_year})
def for_each_pupil(request, g, p, for_each):
pupil = Pupil.objects.all()
content = {'pupil': pupil.get(id=for_each), 'grades': grade_nums,
'unique_grades': unique_grades, 'current_year': current_year}
return render(request, 'accounts/for_each_pupil.html/', content)
finally my template:
{% extends 'accounts/maktab.html' %} {% load static %} {% block content %}
<!-- css > sinflar.css -->
<h3 id="to_top"></h3>
{% include "accounts/special_icons/plus-minus.html" %}
<div class="row">
{% for i in grade %}
<div class="pupil">
<div class="first fir">
<form action="" method="POST">
<input type="checkbox" name="todelete" value="{{ i.id }}">
</form>
<img src="#" alt="#" />
</div>
<div class="second sec">
<div>
<a
href="{% url 'pupils' i.grades i.id %}"
style="text-decoration: none; color: aliceblue;"
>
<h3 class="is_m">{{i}} sinfi</h3>
{% if i.motto %}
<h3>Shior: {{i.motto}}</h3>
{% endif %}
</a>
</div>
<button class="shr" onclick="forShrink()">shrink</button>
</div>
</div>
{% empty %}
<h2>
Apologies...<br />
But you have no unique grades yet.
</h2>
{% endfor %}
<div class="pupil pup remove" >
<div class="first fir">
<img src="#" alt="#" id="for_ease"/>
</div>
<div class="second">
<form action="" method="POST">
{% csrf_token %} {% if Unique.non_field_errors %}
<style>
.remove {
opacity: 1;
height: 600px;
position: relative;
pointer-events: all;
}
</style>
{{ Unique.non_field_errors }} {% endif %}
<div class="field nums def">
{{ Unique.grades.errors }}
<label for="{{ Unique.grades.id_for_label }}"
>Sinf raqami</label
>
{{ Unique.grades }}
</div>
<div class="field letters def">
<h3>Sinf raqami: {{ g }}</h3>
<label for="{{ Unique.A_B_C.id_for_label }}"
>Sinf Belgisi</label
>
{{ Unique.A_B_C }}
</div>
<div class="field motto">
{% if Unique.motto.errors %}
<style>
.remove {
opacity: 1;
height: 600px;
position: relative;
pointer-events: all;
}
</style>
{{ Unique.motto.errors }} {% endif %}
<label for="{{ Unique.motto.id_for_label }}"
>motto</label
>
{{ Unique.motto }}
</div>
<button type="submit" name="submit" id="subm">
Add
</button>
<br />
<button id="subm">
<a
href="#to_top"
style="text-decoration: none; color: aliceblue;"
onclick="remove()"
>Cancel</a
>
</button>
</form>
</div>
</div>
</div>
<script>
selectElement("id_grades", "{{ g }}");
function selectElement(id, valueToSelect) {
let element = document.getElementById(id);
element.value = valueToSelect;
}
</script>
{% endblock %}
And again main purpose is to have all CRUD in one template without url routing for each object.
Second is to have 'delete by check' option.
Please if you know the answer don't keep silence. Would be very glad! Thanks!