Sorry I am quite new to Django.
Ok in my project, every blogpost has their own group of members. You are only a member if your interest status is 'Accepted', and you get auto added to the member list. Every user can "submit interest" to any blogpost.
So now on the account page of the user, i want to query the blog posts that the user is a member to (aka interest status = "accepted")
I also want to query ALL the blog posts that the user has submitted interest to and that they are waiting to be accepted. to (aka interest status = "pending" and not a member yet)
In case you are confused, the members is a field of BlogPost model, and the status is a field in the InterestInvite model :).....
so in my template i want to have the title of ALL those blogpost that I am a member to and those blogpost where my interest is still pending status to be displayed. And when I click on the title, I will be directed to that particular blog post. Can anyone share how this querying can be done?
Problem i am facing is that i cannot use blog_post = get_object_or_404(BlogPost, slug=slug) in my views.py because they will say NameError because slug not defined. And I have no foreign key in my Account model to the BlogPost model. My foreign key is only in the BlogPost model.
Not sure if anyone has any solution to the querying and how I can display the info on the template. Thank you!
models.py
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
class BlogPost(models.Model):
title = models.CharField(max_length=50, null=False, blank=False, unique=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(blank=True, unique=True)
members = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name="members")
class Interest(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
blog_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE)
class InterestInvite(models.Model):
ACCEPT = "ACCEPT"
DECLINE = "DECLINE"
PENDING = "PENDING"
STATUS_CHOICES = [
(ACCEPT, "accept"),
(DECLINE, "decline"),
(PENDING, "pending"),
]
interest = models.OneToOneField(Interest, on_delete=models.CASCADE, related_name="interest_invite")
status = models.CharField(max_length=25, choices=STATUS_CHOICES, default=PENDING)
urls.py
path('<user_id>/', account_view, name="view"),
views.py
def account_view(request, *args, **kwargs):
context = {}
user_id = kwargs.get("user_id")
try:
account = Account.objects.get(pk=user_id)
context['account'] = account
except:
return HttpResponse("Something went wrong.")
if account:
context['id'] = account.id
context['username'] = account.username
context['email'] = account.email
context['profile_image'] = account.profile_image.url
context['hide_email'] = account.hide_email
context['biography'] = account.biography
blog_posts = BlogPost.objects.filter(author=account)
context['blog_posts'] = blog_posts
return render(request, "account/account.html", context)
account.html
{% if request.user in blog_post.members.all %}
{% endif %}
Django automatically sets an auto primary field in your BlogPost Model. So you can access it via:
blog_post = get_object_or_404(BlogPost, pk=pk)
And since you have a ForeignKey to the user you can query everything like:
user.blogpost_set.all() # get all blog posts of the user
user.interest_set.all() # get all interests of the user
user.interest_set.filter(
interest_invite__status="PENDING"
) # get all interest with status pending of the user
Or you can go through User Model like:
User.objects.filter(
blogpost__interest__interest_invite__status="PENDING"
).distinct() # get all users with interestinvite status PENDING
User.objects.filter(
blogpost=b, blogpost__interest__interest_invite__status="ACCEPTED"
).distinct() # get all users of a specific BlogPost with status ACCEPTED
Related
I try to build follow system, when I tried to let the users see the posts of the users which that follow them I got error Unsupported lookup 'following' for CharField or join on the field not permitted
The profiles model
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(
verbose_name="date joined", auto_now_add=True
)
following = models.ManyToManyField(
settings.AUTH_USER_MODEL, blank=True, related_name="follow"
)
The posts model
class Video(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
video = models.FileField(upload_to='post-videos')
title = models.CharField(max_length=100)
description = models.TextField(null=True, blank=True)
my view
class home_screen_view(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
logged_in_user = request.user
post = Video.objects.filter(
author__username__following__in=[logged_in_user.id]
).order_by('-created_date')
context = {
'post_list': post,
}
return render(request, "personal/home.html", context)
Your post = ... query is wrong because you are retrieving the author's username (which exists), but then treating it as if this field were a foreign key or m2m with a property following, which is flat out wrong. username is a CharField.
Instead let's try to clarify the concepts that will be useful to making our solution:
Each Video, has an author.
Each author, is a user.
Each user has an m2m relationship following which is the users he follows.
Each user has a REVERSE m2m relationship follow which is the users that follow him.
Therefore in your view, your query should be:
post = Video.objects.filter(
author__follow=logged_in_user
).order_by('-created_date')
With django M2Ms, so long as the logged_in_user is in that list, ...follow=logged_in_user will return true and filter the item in.
I'm currently creating a Social platform with Django. Right now, I'm developing homepage and want to show posts matching a userfield.
This is my Post model:
class Discussion(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Account, on_delete=models.CASCADE)
post = models.TextField()
date = models.DateTimeField(default=timezone.now)
This is user account model:
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
classid = models.CharField(max_length=10)
This is view:
#login_required(login_url='login')
def home(request):
if request.method == 'GET':
discussions = Discussion.objects.get(post=Account.classid).order_by('-date')
form = PostDiscussionForm()
return render(request, 'app/home.html', {'discussions':discussions,'form':form})
else:
form = PostDiscussionForm(request.POST)
newdisscussion = form.save(commit=False)
newdisscussion.author = request.user
newdisscussion.save()
return redirect('home')
I want to show only logged users matching their classid (from user account model)
What I gather from here, is that you want to show which users are currently online/logged in? For that you'll need to store additional information when logging like, add a boolean field in the user model indicating whether or not the user has logged in and then filter based on that field.
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
logged_in = models.BooleanField(default=False)
classid = models.CharField(max_length=10)
Now add additional logic which sets this field to true when the user eventually logs in from your /login route.
Then Filter using:
$ return Account.objects.filter(logged_in==True)
This will return you all users that have currently logged in, if you're not using any serializers, than use value_list for getting the values only rather than the whole user objects.
$ return Account.objects.filter(logged_in==True).values_list('classid', flat=True)
I am trying to get the Users of a particular city in the userprofile model. My code is as below:
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
city = models.CharField(max_length=250, default='Bengaluru', blank=False, null=False)
views.py
def home(request):
users = User.objects.filter(is_staff=False).prefetch_related(
Prefetch('userprofile',
queryset = UserProfile.objects.filter(city='Mumbai')
)
)
context = { 'users': users }
return render(request, 'users/home.html', context)
But in the above code, users object contains all the users but the userprofiles only where the city is Mumbai. What I want is do get only the users whose userprofile city is Mumbai. Not all the users. How can I do that? What am I doing wrong here?
I found the answer to my problem:
users = User.objects.filter(
is_staff=False,
userprofile__city='Mumbai'
).prefetch_related(
Prefetch('userprofile',
queryset = UserProfile.objects.filter(city='Mumbai')
)
)
If there is any other better way then please post your answer.
I have a list of employees who work at a site. Each site is owned by a User (using Django's standard user model).
I want to create a form that adds an employee and automatically links them to a site dependent on who the authenticated user is:
models.py:
class Employee(models.Model):
site = models.ForeignKey(Site, null=True)
employee_name = models.CharField(default='name', max_length=128, blank=False, null=False)
class Site(models.Model):
user = models.ForeignKey(User)
site_name = models.CharField(max_length=128, blank=False, null=False)
views.py:
site_profile = Site.objects.get(user=request.user)
if request.method == "POST":
form = EmployeeAddForm( request.POST )
if form.is_valid():
obj = form.save(commit=False)
obj.site = site_profile
obj.save()
return redirect('dashboard_home')
form = EmployeeAddForm()
return render(request, "dashboard/employees.html", {'form': form })
forms.py:
class EmployeeAddForm(forms.ModelForm):
class Meta:
model = Employee
fields = ( 'employee_name')
This code will add the employee to the database, but in django admin, list_display = 'site' results in Site object not the actual site name. It does not appear that the employee is linked to the site.
If I use obj.site = site_profile.id (adding .id), I get the error Cannot assign "1": "Employee.site" must be a "Site" instance.
Found the error: the above code is correct, I simply had a tab ordering error in my Site modeL
class Site(models.Model):
...
def __str__(self):
return self.site_name
def should have been inserted 1 tab inwards.
My creation is a basic project about ticketing, users and assets. It's a typical application that companies have to keep a list of who has what and what issues are occurring.
So far I have (models):
**** Tickets ******************
class Ticket(models.Model):
category = models.ForeignKey('TicketCategory')
issue = models.CharField(max_length=100)
user = models.ForeignKey('Users', blank=True,null=True,related_name="tickets")
owner = models.ForeignKey(User)
**** Users *********************
class Users(models.Model):
firstname = models.CharField(max_length=100)
lastname = models.CharField(max_length=100)
email = models.CharField(max_length=100, blank=True)
business = models.ForeignKey('Business', blank=True, null=True,related_name="users")
owner = models.ForeignKey(User)
class Meta:
db_table = 'users'
verbose_name_plural = "users"
ordering = ["lastname"]
**** Assets *********************
class Assets(models.Model):
serial = models.CharField(unique=False, max_length=100)
brand = models.CharField(max_length=100)
user = models.ForeignKey('Users', blank=True, null=True, related_name="assets")
location = models.ForeignKey('AssetLocation', blank=False, null=False, related_name="assets")
owner = models.ForeignKey(User)
I have stripped them down a bit to exclude the useless info. There are others also like AssetsLocations, Categories etc., all of them in the same pattern - the owner is added in the end as a Foreign Key.
I have created some form of authentication, so every logged in user will have his own tickets, assets, and users (employees actually). Filtering is needed so the data of each user ONLY are displayed after every successful authentication.
I am using CBVs and override the get_queryset to enable filtering by the user currently logged in:
Views.py
class TicketList(ListView):
template_name = 'assets/ticket_list.html'
def get_queryset(self):
user = self.request.user
return Ticket.objects.filter(owner_id=user.id).select_related('user','asset','category')
def get_context_data(self, **kwargs):
context = super(TicketList, self).get_context_data(**kwargs)
context['totalTickets'] = self.get_queryset().count()
context['tickets'] = self.get_queryset().select_related('user','asset','category')
return context
Everything works successfully and only logged_in user's data are shown. Then I am trying to create a new Ticket:
class TicketCreate(CreateView):
fields = [ 'category', 'issue', 'user']
template_name = 'assets/ticket_form.html'
def get_queryset(self):
user = self.request.user
return Ticket.objects.filter(owner_id=user.id)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.owner_id = self.request.user.id
self.object.save()
return HttpResponseRedirect(self.get_success_url())
success_url = reverse_lazy('ticket_list')
I am getting everything posted in the form template by using {{ form.category }}, {{ form.issue }} etc. The issue I am facing is that the drop-down boxes displayed in the form, for example the {{ form.user }} should be displaying only the users where user.owner = self.request.user.id, in simple words: the users that the owner created. Instead of it, all the users in the database are displayed.
Isn't it obvious which is the question :) ?