So i am testing a the inlineformset feature in Django, and so far have the following code:
Application name: Example
models.py
from django.db import models
from django.core.urlresolvers import reverse
class Recipe(models.Model):
pub_date = models.DateTimeField('Date Published', auto_now_add= True)
title = models.CharField(max_length=200)
instruction = models.TextField()
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('recipe_edit', kwargs={'pk': self.pk})
class Ingredient(models.Model):
recipe = models.ForeignKey(Recipe, related_name="ingredients")
ingredient = models.CharField(max_length=255)
def __unicode__(self):
return self.recipe_id
def get_absolute_url(self):
return reverse('ingredient_edit', kwargs={'pk': self.recipe_id})
forms.py
from django import forms
from models import Recipe, Ingredient
from django.forms.models import inlineformset_factory
MAX_INGREDIENTS = 5
IngredientFormSet = inlineformset_factory(
Recipe,
Ingredient,
can_delete=False,
extra=MAX_INGREDIENTS
)
class UserSubmittedRecipeForm(forms.ModelForm):
class Meta:
model = Recipe
exclude = ('pub_date',)
views.py
def recipe_create(request, template_name='example/recipe_form.html'):
if request.POST:
form = UserSubmittedRecipeForm(request.POST)
if form.is_valid():
recipe = form.save(commit=False)
ingredient_formset = UserSubmittedRecipeForm(request.POST, instance=recipe)
if ingredient_formset.is_valid():
recipe.save()
ingredient_formset.save()
return redirect('recipe_list')
else:
form = UserSubmittedRecipeForm()
ingredient_formset = IngredientFormSet(instance=Recipe())
return render(request, template_name, {
"form": form,
"ingredient_formset": ingredient_formset
}, context_instance=RequestContext(request))
Views version 2
This does not work either.
def recipe_create(request, template_name='example/recipe_form.html'):
if request.POST:
form = UserSubmittedRecipeForm(request.POST)
if form.is_valid():
created_recipe = form.save()
ingredient_formset = UserSubmittedRecipeForm(request.POST, instance=created_recipe)
if ingredient_formset.is_valid():
ingredient_formset.save()
return redirect('recipe_list')
else:
form = UserSubmittedRecipeForm()
recipe = Recipe()
ingredient_formset = IngredientFormSet(instance=recipe)
return render(request, template_name, {
"form": form,
"ingredient_formset": ingredient_formset
}, context_instance=RequestContext(request))
The problem that i am having is that the "ingredient" field from the Ingredient model is not saved every time the form is submitted.
There is no error displayed. The rest of the field from the Recipe model gets saved properly.
Does anyone know why is this?
Should
ingredient_formset = UserSubmittedRecipeForm(request.POST, instance=created_recipe)
be
ingredient_formset = IngredientFormSet(request.POST, instance=created_recipe)?
If that is the problem, you have made it in both views.
There was a typo in version 2 of views. Check whether this solves your problem
Views.py version 2:
def recipe_create(request, template_name='example/recipe_form.html'):
if request.POST:
form = UserSubmittedRecipeForm(request.POST)
if form.is_valid():
created_recipe = form.save()
#There was a typo here
ingredient_formset = IngredientFormSet(request.POST, instance=created_recipe)
if ingredient_formset.is_valid():
ingredient_formset.save()
return redirect('recipe_list')
else:
form = UserSubmittedRecipeForm()
recipe = Recipe()
ingredient_formset = IngredientFormSet(instance=recipe)
return render(request, template_name, {
"form": form,
"ingredient_formset": ingredient_formset
}, context_instance=RequestContext(request))
Related
I want to set value, but i don't know how do it.
Error:
RelatedObjectDoesNotExist at /comments/
commentsTabl has no avtor.
Request Method: GET
Request URL: http://localhost:8000/comments/
Django Version: 4.0.2
Exception Type: RelatedObjectDoesNotExist
Exception Value:
commentsTabl has no avtor.
Exception Location: D:\python39\lib\site-packages\django\db\models\fields\related_descriptors.py, line 197, in get
Python Executable: D:\python39\python.exe
Python Version: 3.9.6
Python Path:
['D:\Django\ForumXT\first',
'D:\python39\python39.zip',
'D:\python39\DLLs',
'D:\python39\lib',
'D:\python39',
'D:\python39\lib\site-packages']
Server time: Thu, 07 Apr 2022 12:20:35 +0000
models.py
class commentsTabl(models.Model):
Text = models.TextField(verbose_name='Text')
date = models.DateTimeField(default=timezone.now, verbose_name='date')
avtor = models.ForeignKey(User, verbose_name='avtor', on_delete=models.CASCADE, to_field="username")
def __str__(self):
return f'Comment {self.avtor} at {self.date}'
class Meta:
verbose_name = "Comment"
verbose_name_plural = "Comments"
views.py
def comments(request):
data = {
'com': reversed(commentsTabl.objects.all())
}
if request.method =="POST":
form = commentsTabl(request.POST)
if form.is_valid():
form.save()
else:
form = commentsTabl()
return render(request, 'home/comments.html', data, {'form':form})
In models.py
class Comment(models.Model):
Text = models.TextField(verbose_name='Text')
date = models.DateTimeField(auto_add_now=True, verbose_name='date')
avtor = models.ForeignKey(User, verbose_name='avtor', on_delete=models.CASCADE)
def __str__(self):
return 'Comment {} at {}'.format(self.avtor, self.date)
class Meta:
# Order comments in reverse order
# ordering = ["-id"]
In views.py
from .forms import CommentForm
from .models import Comments
from django.http import HttpResponseRedirect
from django.urls import reverse
def comments(request):
# Retrive all comments from database
comments = Comment.objects.all()
# Reverse ...
comments = reversed(comments)
# Form with no data (unbound form)
form = CustomerForm()
context = {"comments": comments, "form": form}
# when method is post
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
# Don't save the form to database
comment = form.save(commit=False)
# Add user to the comment
comment.avtor = request.user
# Save comment to database
comment.save()
return HttpResponseRedirect(reverse('some url name'))
# when form is invalid
else:
# Re-render the form with errors and data
context["form"] = form
return render(request, "home/comments.html", context)
# when method is not post
else:
return render(request, "home/comments.html", context)
In forms.py
from django.forms import ModelForm
from .models import Comment
# Create your forms here
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ("Text", "date",)
# or
# exclude = ("avtor",)
# fields = "__all__"
Important
python manage.py makemigrations
python manage.py migrate
In comments.html you will have access to form and comments
I tryed to add validation to ContactModel, by doing Forms.py but I went too far away with it and now dont know to fix it. Can someone help ?
def addContact(request):
form = ContactForm()
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# form = Contact(
# full_name = request.POST ('fullname'),
# relationship = request.POST ('relationship'),
# email = request.POST ('email'),
# phone_number = request.POST ('phone-number'),
# address = request.POST ('address'),
# )
form.save()
return redirect('/contact')
context = {'form': form}
return render(request, 'contact/new.html', context)
def contactProfile(request,pk):
contact = Contact.objects.get(id=pk)
return render(request, 'contact/contact-profile.html', {'contact': contact})
In my opinion in Views I have big mess.. When I fill up all fields data isn't sending to database.
forms.py:
from django.forms import ModelForm
from .models import Contact
class ContactForm(ModelForm):
class Meta:
model = Contact
fields = '__all__'
models.py:
from django.db import models
# Create your models here.
class Contact(models.Model):
full_name = models.CharField(max_length=500)
relationship = models.CharField(max_length=50)
email = models.EmailField(max_length=254)
phone_number =models.CharField(max_length=20)
address = models.CharField(max_length=100)
def __str__(self):
return self.full_name
It seems that your form is not valid and it redirects always to contact.
You should to use redirect only if the form is valid. Otherwise you will never see which errors your form contains.
Try the following code:
def addContact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form.save()
return redirect('/contact')
else:
form = ContactForm()
context = {'form': form}
return render(request, 'contact/new.html', context)
I want to set a default value in a form and it will be reset as approval = False in every update. I tried something but it did not work it doesn't change. How can I fixed it?
forms.py
class UpdateDoaTableForm(forms.ModelForm):
approval = forms.BooleanField(required=False,
initial=False,
label='Approved',
widget=forms.HiddenInput()
)
class Meta:
model = DoaTable
fields = ('limit', 'approval')
views.py
def update_limit(request, id):
limiting = get_object_or_404(DoaTable, id=id)
form = UpdateDoaTableForm(request.POST or None, request.FILES or None, instance=limiting)
limiting_item = DoaTable.objects.filter(id=id)
if form.is_valid():
form.save()
return redirect('approvals:update_limit_list')
context = {
'form': form,
'limiting_item': limiting_item,
}
return render(request, 'limitUpdate.html', context)
models.py
class DoaTable(models.Model):
...
approval = models.BooleanField(default=False)
I edit my code and it is working now.:
views.py
if form.is_valid():
update_form = form.save(commit=False)
update_form.approval = False
update_form.save()
return redirect('approvals:update_limit_list')
When I try to save a post, the post is saved, but current user is not registered and the post is duplicated with a blank entry and the current user is not stored.
For adding the post I use not the admin app but a personal template and form.
See the problem:
This is my view code:
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from .forms import NewAdminPostForm
from .models import Post, Category
# Create your views here.
def home(request):
posts = Post.objects.all()
categories = Category.objects.all()
posts_last = Post.objects.order_by('-created_at')[0:3]
return render(request, 'front/blog-list.html', {'posts': posts,
'categories': categories, 'posts_last': posts_last})
#login_required
def newadminpost(request):
if request.method == 'POST':
form = NewAdminPostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
Post.objects.create(
message=form.cleaned_data.get('message'),
category_id=post.category_id,
created_by=request.user
)
#post.save()
return redirect('listadminpost')
else:
form = NewAdminPostForm()
return render(request, 'back/new-post-blog.html', {'form': form})
#login_required
def listadminpost(request):
posts = Post.objects.all()
return render(request, 'back/list-post-blog.html', {'posts': posts})
Form of my Blog:
from django import forms
from .models import Post, Category
class NewAdminPostForm(forms.ModelForm):
title = forms.CharField(label="Titre de l'article", max_length=255,)
message = forms.CharField(widget=forms.Textarea(),
max_length=4000,
help_text="Contenu de l'article")
pre_message = forms.CharField(label="Message de prévisu",
widget=forms.Textarea(),
max_length=4000,
help_text="Contenu de l'article")
class Meta:
model = Post
fields = ['title','meta_desc','message','pre_message','category']
Model of my Blog:
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=255, unique=True)
description = models.TextField(max_length=1000)
def __str__(self):
return self.name
def get_categories_count(self):
return Category.objects.filter(post__category=self).count()
class Post(models.Model):
title = models.CharField(max_length=255)
meta_desc = models.TextField(max_length=320, null=True)
pre_message = models.TextField(max_length=4000, null=True)
message = models.TextField(max_length=4000)
category = models.ForeignKey(Category, on_delete='cascade')
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE,
blank=True, null=True)
def __str__(self):
return self.title
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.create
your code:
post.save()...Post.objects.create(
from the link above:
A convenience method for creating an object and saving it all in one step. Thus:
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
and:
p = Person(first_name="Bruce", last_name="Springsteen")
p.save(force_insert=True)
are equivalent.
So what you do in your code:
you save post object created from form
you create and save another Post instance by calling create method
choose any of them, just one, and this will avoid duplicates.
Instead of doing this:
#login_required
def newadminpost(request):
if request.method == 'POST':
form = NewAdminPostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
Post.objects.create(
message=form.cleaned_data.get('message'),
category_id=post.category_id,
created_by=request.user
)
#post.save()
return redirect('listadminpost')
else:
form = NewAdminPostForm()
return render(request, 'back/new-post-blog.html', {'form': form})
You could do this: cleaner, easier to read, more up-to-date, and easier to maintain:
class AdminCreateView(LoginRequiredMixin, generic.CreateView):
model = Request
form_class = RequestForm
def form_valid(self, form):
result = super(AdminCreateView, self).form_valid(form)
title = form.cleaned_data.get('title')
meta_desc = form.cleaned_data.get('meta_desc')
message = form.cleaned_data.get('message')
# and so on. if there's something you refuse (ex title empty) do this:
if not title:
form.add_error('title', _("Precise the title"))
return self.form_invalid(form)
Post.objects.create(message=message,
meta_desc=meta_desc,
title=title,) # and so on
return result
I am trying to have users delete and edit post they create. I was told "Post.user needs to be an object instance what you wrote is incorrect." but I am still newer to django and would like to know the steps to do this as I created this project with some help.
here is my models
from django.db import models
from django.db.models import Count, QuerySet, F
from django.utils import timezone
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.db.models.signals import pre_save
from django.utils.text import slugify
from markdown_deux import markdown
from django.utils.safestring import mark_safe
from taggit.managers import TaggableManager
from comments.models import Comment
def upload_location(instance, filename):
return "%s/%s" %(instance.slug, filename)
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1 )
title = models.CharField(max_length=75)
slug = models.SlugField(unique=True)
image = models.ImageField(
upload_to=upload_location,
null=True,
blank=True,
width_field="width_field",
height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
description = models.TextField()
tags = TaggableManager()
public = models.BooleanField(default=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
created = models.DateTimeField(auto_now_add=True, auto_now=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"slug": self.slug})
class Meta:
ordering = ["-created", "-updated" ]
def get_markdown(self):
description = self.description
markdown_text = markdown(description)
return mark_safe(markdown_text)
#property
def comments(self):
instance = self
qs = Comment.objects.filter_by_instance(instance)
return qs
#property
def get_content_type(self):
instance = self
content_type = ContentType.objects.get_for_model(instance.__class__)
return content_type
def create_slug(instance, new_slug=None):
slug = slugify(instance.title)
if new_slug is not None:
slug = new_slug
qs = Post.objects.filter(slug=slug).order_by("-id")
exists = qs.exists()
if exists:
new_slug = "%s-%s" %(slug, qs.first().id)
return create_slug(instance, new_slug=new_slug)
return slug
def pre_save_post_receiver(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = create_slug(instance)
pre_save.connect(pre_save_post_receiver, sender=Post)
Here is my views
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render, get_object_or_404, redirect
from django.core.exceptions import PermissionDenied
from comments.forms import CommentForm
from comments.models import Comment
from .forms import PostForm
from .models import Post
def post_main(request):
return render(request, "base2.html")
#login_required
def post_create(request):
form = PostForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
# message success
messages.success(request, "Successfully Created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
return render(request, "post_form.html", context)
#login_required
def post_update(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
form = PostForm(request.POST or None, request.FILES or None, instance=instance)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
messages.success(request, "Post Saved")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"title": instance.title,
"instance": instance,
"form":form
}
return render(request, "post_form.html", context)
def post_user(request):
return HttpResponse("<h1>Users Post</h1>")
#login_required
def post_detail(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
initial_data = {
"content_type": instance.get_content_type,
"object_id": instance.id
}
form = CommentForm(request.POST or None, initial=initial_data)
if form.is_valid() and request.user.is_authenticated():
c_type = form.cleaned_data.get("content_type")
content_type = ContentType.objects.get(model=c_type)
obj_id = form.cleaned_data.get('object_id')
content_data = form.cleaned_data.get("content")
parent_obj = None
try:
parent_id = int(request.POST.get("parent_id"))
except:
parent_id = None
if parent_id:
parent_qs = Comment.objects.filter(id=parent_id)
if parent_qs.exists() and parent_qs.count() == 1:
parent_obj = parent_qs.first()
new_comment, created = Comment.objects.get_or_create(
user = request.user,
content_type= content_type,
object_id = obj_id,
content = content_data,
parent = parent_obj,
)
return HttpResponseRedirect(new_comment.content_object.get_absolute_url())
comments = instance.comments
context = {
"title": instance.title,
"instance": instance,
"comments": comments,
"comment_form":form,
}
return render(request, "post_detail.html", context)
#login_required
def post_feed(request):
queryset_list = Post.objects.all()
query = request.GET.get("q")
if query:
queryset_list = queryset_list.filter(
Q(title__icontains=query)|
Q(tags__icontains=query)|
Q(content__icontains=query)|
Q(user__first_name__icontains=query) |
Q(user__last_name__icontains=query)
).distinct()
paginator = Paginator(queryset_list, 8) # Show 25 contacts per page
page_request_var = "page"
page = request.GET.get(page_request_var)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
queryset = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
queryset = paginator.page(paginator.num_pages)
context = {
"object_list": queryset,
"title": "List",
"page_request_var": page_request_var,
}
return render(request, "post_feed.html", context)
#login_required
def post_delete(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
if request.user == Post.user:
instance.delete() # or save edits
messages.success(request, "Successfully Deleted")
return redirect("posts:feed")
else:
raise PermissionDenied # import it from django.core.exceptions
return redirect("posts:feed")
def privacy(request):
return render(request, "privacy.html")
def post_about(request):
return HttpResponse("<h1>About Page</h1>")
def home(request):
return render(request, "base2.html")
Let me know if any other information is needed.
You are almost there.
in delete, your check should be:
request.user == instance.user
instead of
request.user == Post.user
Similarly in post_update, you could do:
if instance.user == request.user:
#Now, allow update
Also, it might be a good idea to check for the request type. Example:
if request.method == "POST":
This way, this check would only happen if it is a POST type