I new to django and I am trying to make a web application. I have this page page image and I want to delete one post when I press the delete button. How can I do that? This is my modal for 'Post' :
class Post(models.Model):
created_date = models.DateTimeField()
title = models.CharField(max_length=100)
profile_image = models.ImageField(upload_to='poze', blank=True, null=True)
text = models.CharField(max_length=1000, default='Nimic', blank=True)
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
I've been looking for delete methods, but I've always found form-only methods and I don't use form. Thank you.
In you html :
Delete
assuming that you are using a for loop :
{% for p in posts %}
In your urls :
path('delete/<post_id>',views.delete_post,name='delete')
In your views :
def delete_post(request,post_id=None):
post_to_delete=Post.objects.get(id=post_id)
post_to_delete.delete()
return HttpResponseRedirect(#name of the view function that returns your posts page)
And that's it
EDIT
This method deletes data from your database directly. So I recommend you add the #login_required decorator to your delete_post view function to protect your post. You can also make it accessible only for admin users or post owners in your html (Example : only users who have staff role can see the delete link)
{% if user.is_staff %}
<a ...>Delete</a>
{% endif %}
You need to pass argument with post id. It would like something like this
p = Post.objects.get(pk=2)
p.delete()
You should create a new field in the database table. Whenever you are deleting the data then you should change the delete field.
class Post(models.Model):
created_date = models.DateTimeField()
title = models.CharField(max_length=100)
profile_image = models.ImageField(upload_to='poze', blank=True, null=True)
text = models.CharField(max_length=1000, default='Nimic', blank=True)
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
delete_flag = models.BooleanField(default=False)
And whenever you are should the data then you should filter the data on the delete flag
Post.objects.filter(delete_flag=False)
Though it is subjective and I don't know you use case, but still as a beginner its better to start with this practice.
Read More
Article 2
Related
I’m new to Django and am trying to show filter options that are only relevant to the user - for example, my app has Message and Automation classes with a many:many relationship, but my filter shows a select option with automations created by other users rather than only those created by the logged-in user.
How can I get it to only show those created by the current user?
The view:
#login_required(login_url='login')
#allowed_users(allowed_roles=['admin', 'customer'], own_account_only=True)
def message_list(request, pk):
account = Account.objects.get(id=pk)
messages = account.message_set.all()
filter = MessageFilter(request.GET, queryset=messages)
messages = filter.qs
context = {'account': account,
'messages': messages, 'filter': filter}
return render(request, 'messages/message_list.html', context)
The filter:
class MessageFilter(django_filters.FilterSet):
class Meta:
model = Message # model we’re building filter for
fields = '__all__'
exclude = ['account', 'date_created', 'text', 'subject']
The classes:
class Message(models.Model):
name = models.CharField(max_length=100)
subject = models.CharField(max_length=128)
text = models.TextField()
account = models.ForeignKey(Account, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
automations = models.ManyToManyField('automations.Automation', blank=True)
def __str__(self):
return self.name
class Automation(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=200)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
messages = models.ManyToManyField(Message, blank=True)
def __str__(self):
return self.name
And the HTML:
<form method="get" class="filter-form with-ps hide">
{{filter.form.as_p}}
<button class="button" type="submit">Search</button>
</form>
I’m assuming I need to edit the messages passed into MessageFilter to somehow exclude automations owned by all users, or somehow tell MessageFilter to only show automations etc of the current logged-in user?
Thank you.
Note: the image below shows the messages listed in the table (correct as they're owned by the logged-in user) and an automations filter option which incorrectly includes some automations not owned by the user (e.g. test automation 3)
One way would be to restrict the queryset to exclude messages that the logged-in user should not see
messages = account.message_set.exclude( something = whatever)
whatever will be be based on request.user. However, that will completely restrict what the user can see, not merely the initial default of what the user can see.
Another way is to "doctor" request.GET for initializing the filter. Instead of
filter = MessageFilter(request.GET, queryset=messages)
do
request_get = request.GET.copy()
# mutate request_get based on contents of request.GET and request.user
...
filter = MessageFilter(request_get, queryset=messages)
request_get is mutable, unlike request.GET. You can inspect it to see what if any filters the user has requested. On the first view there won't be any, and you could insert some appropriate ones by assiging appropriate key/value pairs in
request_get. This way the user can override the initial defaults you choose for him.
So I've been search and trying to solve this question for hours and hours and I cant' seem to find an answer.
I have 2 different models flights and Destinations. The Destination is the Parent model, A flight can only have one destination but the Destination can have many flights (one to many relationship).
I would like to access this parent model on the details page of of the flight model. This details page is generated via the url routing and the slug of the flight. Here is what I have for the for the models, views and templates.
models:
class Flight(models.Model):
title = models.CharField( null=True, max_length=60, blank=True)
slug = models.SlugField(max_length=100, null=True, blank=True)
flight_destination = models.ForeignKey(Destination, null=True, blank=True, on_delete=models.SET_NULL)
class Destination(models.Model):
title = models.CharField( null=True, max_length=60, blank=True)
featuredimage = models.ImageField(null=True, blank=True, upload_to ='media/')
slug = models.SlugField(max_length=100, null=True, blank=True)
Each of these classes has an id for its primary key and I've connected all my flights to the correct destination.
Here is what I have for my view.
def flight_detail(request, slug):
return render(request,"flight/detail.html",context= {'flight': Flight.objects.get(slug=slug), 'destination': Destination.objects.filter(id= Flight.objects.get(slug=slug).flight_destination_id)})
Here is the template but it which doesn't throw an error but it displays nothing
<h3 class="pb-3">
{{ destination.title }}
</h3>
I feel like this should be an extremely common question with tons of straight forward answers but I can't seem to find anything. Any help would be greatly appreciated.
You can access the flight_destination directly in the flight object, you could get the flight object outside the render method to make it clearer and have access to the destination attribute object like this:
def flight_detail(request, slug):
flight = Flight.objects.get(slug=slug)
return render(request, "flight/detail.html",
context = {
'flight': flight,
'destination': flight.flight_destination
}
)
Exactly what I was looking for, thanks! From the time that I made this post I was actually able to get my original one to work using a forloop on the template, but I feel your solution is much cleaner and a more proper way of achieving this. Thanks again!
I have the following models:
class Project(models.Model):
name = models.CharField(max_length=300, unique=True)
description = models.CharField(max_length=2000)
class TemporaryUser(models.Model):
username = models.CharField(max_length=400)
project = models.ForeignKey(
Project,
on_delete=models.CASCADE,
related_name='users'
)
class QuestionSession(models.Model):
project = models.ForeignKey(
Project,
on_delete=models.CASCADE,
related_name='sessions',
blank=True,
null=True,
default=None
)
class Question(models.Model):
# stores the main json object with all required information
description = JSONField(
max_length=10000, blank=True, null=True, default=None
)
question_session = models.ForeignKey(
QuestionSession,
on_delete=models.CASCADE,
related_name='questions',
blank=True,
null=True,
default=None
)
class Answer(models.Model):
question = models.ForeignKey(
Question,
related_name='answers_list',
on_delete=models.CASCADE)
answer = models.CharField(max_length=500)
answered_by = models.ForeignKey(
TemporaryUser,
on_delete=models.CASCADE,
related_name='answers',
blank=True,
null=True,
default=None
)
In a nutshell, my app contains questions, session is a collection of questions, and a project is a collection of sessions. All users are unique per project.
I can fetch all users and all answers within a specific project with the following:
TemporaryUser.objects.all().filter(project__id=project_id)
How can I do the same within a session? I don't really know how to do it, I need to filter users by session, is there a way how to do it with my relations?
Do you mean like:
TemporaryUser.objects.filter(project__sessions__id=id)
I think its cleaner to use reverse relation here:
session = QuestionSession.objects.first()
session.project.users.all()
# as User model has a FK with Project , and it has related_name="users"
You can use this in your template as well:
{% for qs in questionsessions %} // questionsessions is the queryset of QuestionSession
{% for user in qs.project.users.all %}
{{ user.username }}
{% endfor %}
{% endfor %}
If you want to fetch the users with only one query, the way to go is:
users = TemporaryUser.objects.filter(project__sessions=id)
However, if you want to fetch more data related to that session, maybe you should consider to fetch from the session itself (see Following relationships backward). Be cautious, as the number of queries to the database is not optimized.
session = Session.objects.get(pk=id)
users = session.project.users.all()
questions = session.questions.all()
You can use select_related and prefetch_related if you want to make less queries. This could be very important if you are interested in fetching data for a list of sessions and not only one.
I am having a tough time with following code.
{% if object.author == user.username %}
That code is not working neither giving error.
So I have articles app inside my django project. I want to make sure that if a user goes to their own post, then only they should be able to see delete and edit links (I will be placing them inside if block).
The Article model is as follows:
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
Here
{{user.username}}
{{object.author}}
both are valid django variables.
{{user.username}}
specifies username of current logged in user
{{object.author}}
specifies author of that particular post.
Please help me out to implement with comparison logic of both variables. I am using python 3.6, django 2.1 and django template language.
Your question would be easier to answer if you posted your models (and formatted your text correctly).
I presume that object.author is actually a ForeignKey to the User model. Therefore, you should compare directly with the user, not with the username attribute of the user:
{% if object.author == user %}
Hi Djangonauts,
How is everyone today, I am new to Django so please forgive any silly mistakes in logic or code. I have a user, a User_Profile and a posts model. I want to give the user badges for the number of posts the user posts. Example if the user posts 3 posts he/she gets a beginner badge and so on...
Below is my user Profile models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_image = models.ImageField(default='', blank=True, null=True)
badge_image = models.ImageField(default='', blank=True, null=True)#maybe default can be "static/images/beginner_image.jpg" but it does not work
posts models.py
User = get_user_model()
class Post(models.Model):
user = models.ForeignKey(User, related_name='posts')
title = models.CharField(max_length=250, unique=True)
slug = models.SlugField(allow_unicode=True, unique=True)
message = models.TextField()
Now I want to achieve something like this:
user = User.objects.get(username=request.user.username)
if user.posts.count >= 3 :
badge_image = '<img src="some image">'# I don't know how to make a image variable in views and models. I know how to use it in Django templates with {{image.url}}
elif user.posts.count >= 20 :
badge_image = '<img src="some image">'
else:
badge_image ='<img src="beginner_image">'
Where do I write this code in the models, in the views? I am sorry if my questions are too basic. None of the projects I learned had a similar scenario
You can do it without ImageField. Use model's #property for this. You need to copy badge images(e.g. badge_img1.jpg, badge_img2.jpg, etc.) to director with static files(check docs how to manage static with Django). Rewrite Profile like this:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_image = models.ImageField(default='', blank=True, null=True)
#property
def badge_image(self):
if self.user.posts.count() >= 20:
badge_image = 'badge_img1.jpg'# I don't know how to make a image variable in views and models. I know how to use it in Django templates with {{image.url}}
elif self.user.posts.count() >= 3:
badge_image = 'badge_img2.jpg'
else:
badge_image ='badge_img3.jpg'
return badge_image
you can display current user's image like this:
{% load static %}
<img src={% static user.profile.badge_image %}>