Problems with converting datetime to string in Django - django

I can't understand why this isn't working because in a Python console it works fine for me...
class Activity(models.Model):
id = models.CharField(max_length=250, primary_key=True)
description = models.CharField(max_length=255, null=False, help_text="Brief description of the activity")
start = models.DateTimeField(default=timezone.now, verbose_name="Planned start date/time", blank=True)
end = models.DateTimeField(default=timezone.now, verbose_name="Planned completion date/time", blank=True)
class Meta:
verbose_name_plural = 'Activities'
def save(self, *args, **kwargs):
self.id = "%s-%s" % (self.description, str(self.start.date()))
super(Activity, self).save(*args, **kwargs)
def __str__(self):
"""
String for representing the Model object (in Admin site etc.)
"""
return f'{self.description}'
But what I get for my self.id field is (using "xx" as description):
"xx-<built-in method date of datetime.datetime object at 0x000001FCBAAA51E0>"

Try to use strftime instead
def save(self, *args, **kwargs):
self.id = "%s-%s" % (self.description, self.start.strftime('%m/%d/%Y'))
super(Activity, self).save(*args, **kwargs)

Related

count the number of posts

I have created a website and want to count user generated posts.
I tried to do it as follows:
models.py
class Blog(models.Model):
user = models.ForeignKey(
User,
related_name='user_blogs',
on_delete=models.CASCADE
)
category = models.ForeignKey(
Category,
related_name='category_blogs',
on_delete=models.CASCADE
)
title = models.CharField(
max_length=250
)
slug = models.SlugField(null=True, blank=True)
banner = models.ImageField(upload_to='blog_banners')
description = RichTextField()
created_date = models.DateField(auto_now_add=True)
def __str__(self) -> str:
return self.title
def save(self, *args, **kwargs):
updating = self.pk is not None
if updating:
self.slug = generate_unique_slug(self, self.title, update=True)
super().save(*args, **kwargs)
else:
self.slug = generate_unique_slug(self, self.title)
super().save(*args, **kwargs)
templates
<span>Posts: <strong>{{account.user_blogs.count}}</strong></span>
but it doesn't work
what is the problem? should I rewrite the code at all?
If you're trying to count posts created by the logged-in user
<span>Posts: <strong>{{ request.user.user_blogs.count }}</strong></span>

"<Post:>" needs to have a value for field "id" before this many-to-many relationship can be used

When i'm trying to add a Post through django admin i get an error that the Post im trying to add needs to have a value for field id. Do you have any idea why?
now = datetime.now()
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
class Meta:
verbose_name_plural = "categories"
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
excerpt = models.CharField(max_length=200)
main_image = models.ImageField()
author = models.ForeignKey(users.models.CustomUser, on_delete=models.CASCADE, related_name='blog_posts', null=True)
content = models.TextField(null=True)
created_at = models.DateTimeField(editable=False)
updated_at = models.DateTimeField(editable=False)
category = models.ManyToManyField(Category, related_name='post_category')
class Meta:
ordering = ['-created_at']
def save(self, *args, **kwargs):
if not self.id:
self.created_at = now
self.updated_at = now
def __str__(self):
return self.title
You need to make a super().save(*args, **kwargs) call. Furthermore using a constant will not work: this will assign the time when you started the server, not the current time, so:
from django.utils.timezone import now
class Post(models.Model):
# …
def save(self, *args, **kwargs):
if not self.id:
self.created_at = now()
self.updated_at = now()
super().save(*args, **kwargs)
You furthermore do not need to specify logic to update the created_at and updated_at field, you can work with auto_now_add=True [Django-doc] and auto_now=True [Django-doc]:
class Post(models.Model):
# …
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
# …
class Meta:
ordering = ['-created_at']
# no save override
def __str__(self):
return self.title

Django: how to create groups?

EXAMPLE to elaborate my problem -> I am the user of the website and i want to create a group. While creating group the website asked me the group_name,group_description ,group_password (as i don't want the group to be public and a person if want to join the group should know the password). now i have given the name and the password to my friends and they can join the group by authenticating with the password of group to successfully join.
ISSUE i am facing -> i have created the password field in models.py. But the password is saved in the database as plane text but not something liked hashed django passwords. secondly, i want in the joining user to authenticate with the password in order to join the group.
models.py
class Group(models.Model):
admin = models.ForeignKey(to=Profile, related_name="admin", on_delete=models.CASCADE)
name = models.CharField(max_length=200, unique=True)
password = models.CharField(max_length=200, default='thinkgroupy')
slug = models.SlugField(allow_unicode=True, unique=True)
group_pic = models.ImageField(upload_to="users/group_images/%y/%m/%d",null=True)
about = models.CharField(max_length=255, null=True, blank=True)
about_html = models.TextField(editable=False, default='', blank=True)
created_at = models.DateTimeField(auto_now=True)
members = models.ManyToManyField(User, through="GroupMember")
def __str__(self):
return "%s" % self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
self.about_html = misaka.html(self.about)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("groups:single", kwargs={"slug": self.slug})
class Meta:
ordering = ["name"]
class GroupMember(models.Model):
group = models.ForeignKey(Group, related_name="memberships")
user = models.ForeignKey(User,related_name='user_groups')
def __str__(self):
return self.user.username
class Meta:
unique_together = ("group", "user")
views.py
class CreateGroup(LoginRequiredMixin, generic.CreateView):
fields = ("name", "description","password")
model = Group
class JoinGroup(LoginRequiredMixin, generic.RedirectView):
def get_redirect_url(self, *args, **kwargs):
return reverse("groups:single",kwargs={"slug": self.kwargs.get("slug")})
def get(self, request, *args, **kwargs):
group = get_object_or_404(Group,slug=self.kwargs.get("slug"))
try:
GroupMember.objects.create(user=self.request.user,group=group)
except IntegrityError:
messages.warning(self.request,("Warning, already a member of {}".format(group.name)))
else:
messages.success(self.request,"You are now a member of the {} group.".format(group.name))
return super().get(request, *args, **kwargs)

How to display two not associated models on one page via admin interface?

I have two models, not connected by ForeignKey. I would to display them on one page in admin interface, in the way like inlines in Django.
I can't associate PostFile with Post, because uploaded medias should be available to every Post which was and will be created in future. I have no idea what I can do if inlines are unavailable.
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published')
)
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique_for_date='publish_date', blank=True)
author = models.ForeignKey(User, related_name='blog_posts', on_delete=models.CASCADE, blank=True)
content = MarkdownxField()
publish_date = models.DateTimeField(default=timezone.now)
creation_date = models.DateTimeField(auto_now_add=True)
last_update_date = models.DateField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
tags = models.ManyToManyField(Tag)
objects = models.Manager()
class Meta:
ordering = [
'-publish_date'
]
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[
self.publish_date.strftime('%Y'),
self.publish_date.strftime('%m'),
self.publish_date.strftime('%d'),
self.slug
])
#https://github.com/neutronX/django-markdownx/issues/83
def formatted_markdown(self):
return markdownify(self.content)
class PostFile(models.Model):
file_name = models.CharField(max_length=200, blank=True)
file_object = models.FileField(upload_to='post_files/')
file_upload_date = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
if not self.file_name:
self.file_name = self.file_object.name
super(PostFile, self).save(*args, **kwargs)
def file_url(self):
return self.file_object.url
def __str__(self):
return self.file_name
I would to receive in output a Post model admin page, where on the bottom I have listed all PostFile objects. This will give me easy and fast acces to PostFile-object url on media folder. I don't want each time to open new tab, and to go to PostFile model admin page to check url of object.

Get models.ManyToManyField selected options count

I can't figure out how to get the manytomanyfield selected options number
my code:
class Author(models.Model):
first_name = models.CharField(max_length=30)
def __unicode__(self):
return u'%s' % (self.first_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
authorsnumbers = models.IntegerField()
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
if not self.id:
self.authorsnumbers = self.authors.count()
super(Event, self).save(*args, **kwargs)
if i select 2 authors, i want authorsnumber to be '2', but how?
This would probably be an easier way to do it:
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
def authorsnumbers(self):
return self.authors.count()
def __unicode__(self):
return self.title
of course you could just use book.authors.count() instead of book.authorsnumber() wherever you need it.