How to save the current User in models while posting? - python

How to save the current User in models while posting?
class Post(models.Model):
author = models.ForeignKey('auth.User') #Please tell me how to save the current user here
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail", kwargs={'pk': self.pk})
def __str__(self):
return self.title

You view in your view.py file have access to user in request object
def save_post(request):
# you have to fill all needed fields. It's just an example
Post.objects.create(author=request.user)
return HttpResponse()

Related

Django datetime fromisoformat: argument must be str

Hi I had this error while try to running server. It may cause by the datetime field. Can someone check it for me.
models.py
class Post(models.Model):
author = models.ForeignKey("auth.User", on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
create_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def get_absolute_url(self):
return reverse("post_detail", kwargs={"pk": self.pk})
def publish(self):
self.published_date = timezone.now
self.save()
def approve_comments(self):
return self.comments.filter(approve_comment=True)
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('mblog.Post', related_name='comments', on_delete=models.CASCADE)
author = models.CharField(max_length=100)
text = models.TextField()
create_date = models.DateTimeField(default=timezone.now)
approve_comment = models.BooleanField(default=False)
def approve(self):
self.approve_comment = True
self.save()
def get_absolute_url(self):
return reverse("post_detail", kwargs={"pk": self.pk})
def __str__(self):
return self.text
views.py
class PostListView(ListView):
model = models.Post
def get_queryset(self):
return models.Post.objects.filter(published_date__lte=timezone).order_by('-published_date')
class DraftListView(LoginRequiredMixin,ListView):
login_url = '/login/'
redirect_field_name = 'mblog/post_list.html'
model = models.Post
def get_queryset(self):
return models.Post.objects.filter(published_date__isnull=True).order_by('created_date')
And had anyway better to set default for the DateTimeField?
Thanks for your time.
I guess you also go through the udemy course, got the same error myself.
Probably not relevant to you anymore, but if someone else had the same problem, it's just a case of adding parenthesis () after timezone.now in Post class in publish method
so it looks like this:
def publish(self):
self.published_date = timezone.now()
self.save()

How do I display comments that are using a foreign key of another model in Django class based views?

I would like to list out the comments on my Post Detail page and wanted to see how I can connect a view to the specific comments for a given post?
Models.py
class Post(models.Model):
owner = models.ForeignKey(
Profile, null=True, blank=True, on_delete=models.SET_NULL)
title = models.CharField(max_length=200)
body = models.TextField()
Post_image = models.ImageField(
null=True, blank=True, default='default.jpeg')
create_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post', kwargs={'pk': self.pk})
class Meta:
ordering = ['-create_date']
class Comment(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
text = models.TextField()
create_date = models.DateTimeField(auto_now_add=True)
Views.py
class PostDetailView(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comment_list'] = Post.comment_set.all()
return context
You can access the detail object of the DetailView with self.object:
class PostDetailView(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comment_list'] = self.object.comment_set.order_by('create_date')
return context

Pass multiple parameters in Django

class Article(models.Model):
Title = models.CharField(max_length = 255)
writing = models.TextField()
category = models.CharField(max_length = 225)
published = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(blank=True, editable=False)
def save(self):
self.slug = slugify(self.Title)
super().save()
def get_absolute_url(self):
url_slug = {'slug':self.slug}
return reverse('artikel:ArticleDetail', kwargs = url_slug)
def __str__(self):
return "{}.{}".format(self.id, self.Title)
i want to build a simple website using django where it could post some articles by form. The problem is how could i post multiple category in one article ? this is form.py below.
from .models import Article
from django.forms import ModelForm
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = [
'title',
'writing',
'category',
]
You can a ManyToManyField to link your post to multiple categories, for example:
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=255)
writing = models.TextField()
category = models.ManyToManyField(Category)
published = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(blank=True, editable=False)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save()
def get_absolute_url(self):
return reverse('artikel:ArticleDetail', kwargs={'slug': self.slug})
def __str__(self):
return '{}.{}'.format(self.id, self.title)
That being said, there already are some packages for this. django-taggit [GitHub] for example, you can install this with:
pip3 install django-taggit
and include 'taggit' to the INSTALLED_APPS list [Django-doc]:
# settings.py
INSTALLED_APPS = [
# …,
'taggit',
# …
]
Then in your models, you can add a TaggableManager to the model:
from django.db import models
from taggit.managers import TaggableManager
class Article(models.Model):
title = models.CharField(max_length=255)
writing = models.TextField()
categories = TaggableManager()
published = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(blank=True, editable=False)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save()
def get_absolute_url(self):
return reverse('artikel:ArticleDetail', kwargs={'slug': self.slug})
def __str__(self):
return '{}.{}'.format(self.id, self.title)
As the documentation specifies, it comes with a form field that allows one to write space-separated and comma-separated tags.

How to save forms in django with foreign key

I'm making a to-do list app and I'm trying to make the create page for an Item. Most of it works except that I don't get it to save in what Todo List to go and therefor get this error. 'Cannot assign "'Home'": "Item.todolist" must be a "TodoList" instance.'
This is my view:
def create_todo(request):
context = {"lists": TodoList.objects.filter(user=request.user)}
if request.method == "POST":
if request.POST.get("create"):
title = request.POST.get("item_title")
date_due = request.POST.get("item_date")
text = request.POST.get("item_note")
todolist = request.POST.get("todolist")
t = Item(
user=request.user,
todolist=todolist,
title=title,
date_due=date_due,
text=text,
complete=False,
)
t.save()
redirect("all-todos-view")
return render(request, "create_todo.html", context)
Here is my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class TodoList(models.Model):
name = models.CharField(max_length=50)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("all-todos-view")
class Item(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
todolist = models.ForeignKey(TodoList, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
date_due = models.DateTimeField(
auto_now=False, auto_now_add=False, blank=True, null=True
)
text = models.TextField(blank=True, null=True)
complete = models.BooleanField(blank=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("all-todos-view")
Try this way
t = Item( title=title,
date_due=date_due,
text=text,
complete=False,
)
t.save(commit=False)
t.user = request.user
t.todolist.name = todolist
t.save()
return redirect("all-todos-view")

Unread posts Django

I've build a blog using Django (very minimal functional blog) and I want to be able to show to the user in my blog only the posts he hasn't read yet.
I have 10,000+ posts and I want to show the user every time he log in a random posts he has not seen yet/
I am new with Django and I not sure I should do it the right way.
I have the Post model:
class Post(models.Model):
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail",kwargs={'pk':self.pk})
def __str__(self):
return self.title
Thank you!
You should use ManyToManyField:
class Post(models.Model):
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
read_users = models.ManyToManyField(User) # Add this line
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail",kwargs={'pk':self.pk})
def __str__(self):
return self.title
You have to keep record of user and which posts he has read. Just like this
class UserReadPost(models.Model):
user = models.ForeignKey(User, releated_name='user_read_posts')
post = models.ForeignKey(Post, releated_name='posts_read_by_users')
read_at = models.DateTimeField(auto_now=True)
You will have to add a record in this table every time a user read some post. You can get all posts which user have not read yet like this.
from django.db.models import OuterRef, Subquery, Exists
post_read_status = UserReadPost.objects.filter(post=OuterRef('post'), user=current_user_object)
Post.objects.all().annotate(has_read=Exists(post_read_status)).exclude(has_read=True).order_by('?')
This can be done using ManyToManyField but adding your own table will give you ability to check when that user read that specific post.

Categories

Resources