How to dynamically insert a value in a Django ModelForm - python

I have a project where users can create a company. However, there is a Theme that needs to be dynamically inserted, once the user chooses a theme on the frontend - more like when you want to choose a template in a no-code builder. Below is my models.py
class Theme(models.Model):
name = models.CharField(max_length=100, null=True)
image = models.ImageField(upload_to='static/images/themes_images', null=True, blank=True)
category = models.CharField(max_length=200, choices=CATEGORY_CHOICES, null=True)
class Company (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, editable=False)
date_created = models.DateField(default=timezone.now, null=True)
company_name = models.CharField(max_length=100, null=True)
theme = models.ForeignKey(Theme, on_delete=models.CASCADE, null=True, blank=True)
For the Theme model, it is only the administrator who will create it and the user will only have to choose it on the front end. Sort of like when choosing a premade template in Weebly. All the Theme Objects will have their own page where the user can visually see which theme to go with:
#login_required(login_url='login')
def theme(request):
themes = Theme.objects.all()
context = {'themes': themes}
return render(request, 'themes.html', context)
I haven't done much with the view, cause I am not sure how to go about it to achieve the desired result.
Themes.html
{% extends 'index.html' %}
{% load static %}
{% block 'title' %} <title>Themes | Simpledocs</title> {% endblock %}
{% block content2 %}
{% endblock %}
{% block content %}
<h2 class="my-4">Choose your theme</h2>
<div class="columns">
{% for t in themes %}
<div class="column is-4">
{{t.name}}<br>
<img src = "/{{t.image}}" height="150px" width="150"/><be>
{{t.category}}<br>
<a class="button" href="#">Choose Theme</a>
</div>
{% endfor %}
</div>
{% endblock %}
So with a click on the above view, the user should be able to select a theme and apply it dynamically in the Company model on the theme entry. I have never dealt with such a challenge and need help here.

It is actually easy. Got the solution.
Create another view that shows individual themes:
{% extends 'index.html' %}
{% load static %}
{% block 'title' %} <title>Themes | Simpledocs</title> {% endblock %}
{% block content2 %}
{% endblock %}
{% block content %}
<h2 class="my-4">Choose your theme</h2>
<div class="columns">
{{single_theme.name}}<br><br>
<img src="/{{single_theme.image}}" /><br><be>
{{single_theme.category}}<br>
<form method="POST">
{% csrf_token %}
<button class="button">Choose Theme</button>
</form>
</div>
{% endblock %}
Create another View showcasing the theme. And execute the change of the Company.theme entry.
#login_required(login_url='login')
def theme_single(request, pk):
single_theme = Theme.objects.get(id=pk)
company = Company.objects.all()
if request.method == 'POST':
for c in company:
c.theme = single_theme
c.save()
return redirect('company')
context = {'single_theme':single_theme}
return render(request, 'theme_single.html', context)
This will change the company.theme model entry to the current theme selected.

Related

Django how to show all comment as child parent relationship in HTML template?

I want to show my all child objects under it's parent in my html template. How to do it in Django?
#html
{%for i in contact %}
{% if not i.parent %}#shwing only parent objects
ticket #parent_id{{i.message}}
#here I want to list all child object of my parent
{%endif%}
{%endfor%}
here is my models.py:
class Contact(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True,related_name='contact_user')
name = models.CharField(max_length=250)
email = models.EmailField(max_length=500)
message = models.CharField(max_length=2000,blank=True,null=True)
parent =models.ForeignKey('self', on_delete=models.CASCADE,
null=True, blank=True, related_name='contact_parent')
sno = models.AutoField(primary_key=True,)
here is my views.py
def UserProfileView(request):
userinfo = UserManagement.objects.filter(username=request.user)
userprofile = UserProfile.objects.filter(user=request.user)
contact = Contact.objects.filter(user=request.user)
form = TicketForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.instance.user = request.user
messages.add_message(request, messages.INFO,'You ticket submitted sucessfully')
form.save()
return redirect('members:user-profile-private')
else:
form = TicketForm()
context={"userinfo":userinfo,"userprofile":userprofile,"form":form,"contact":contact}
return render(request,"members/privateprofile.html",context)
I think you are looking for something like:
query:
Contact.objects.filter(parent__isnull=True)
template:
{% for parent in contact %}
<h1>{{ parent.name }}</h1>
{% if parent.contact_parent.count %}
<ul>
{% for child in parent.contact_parent.all %}
<li>{{ child.name }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
Also, I think you should change the related_name to something like contact_children or just children, remember this should represent the opposite of the field in OneToMany relationship, example:
parent = models.ForeignKey(
"self",
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="contact_children", # opposite of field
)
And to avoid doing too many queries in your template you could use prefetch_related:
Contact.objects.prefetch_related('contact_children').filter(parent__isnull=True)
And the template:
{% for parent in contact %}
<h1>{{ parent.name }}</h1>
{% if parent.contact_children.count %}
<ul>
{% for child in parent.contact_children.all %}
<li>{{ child.name }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
Looks more understandable right?

How can I get item from a model field

I'm a Django beginner, how can I get profile_pic from Profile Model connecting it to 'to_user' field in FriendRequest Model.
I was able to get the names of users in 'to_user' field by this:
{% for data in sent_friend_request %}
{{ data.to_user.username }}
{% endfor %}
How do I get the profile_pic for each users?
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
profile_pic = models.ImageField()
class FriendRequest(models.Model):
to_user = models.ForeignKey(settings.AUTH_USER_MODEL)
from_user = models.ForeignKey(settings.AUTH_USER_MODEL)
def following_view(request, username):
sent_friend_request = FriendRequest.objects.filter(from_user__username=username)
context = {'sent_friend_request':sent_friend_request}
{% if data.to_user.profile_pic %}
<img src="{{ data.to_user.profile_pic }}">
{% endif %}
You can do like this:
{% if data.to_user.profile.profile_pic %}
<img src="{{ data.to_user.profile.profile_pic.url }}">
{% endif %}

Django: can't access OneToOneField after rendering TemplateView Form

I am new to Django and don't understand what really is causing this:
I have a Model Company which has an OneToOneField, creator.
# models.py
class Company(models.Model):
class Meta:
verbose_name = 'Company'
verbose_name_plural = 'Companies'
creator = models.OneToOneField(User, related_name="company", on_delete=models.CASCADE, unique=False, null=True)
name = models.CharField(max_length=50)
I have a TemplateView class to handle get and post requests for creating a Company model:
# views.py
class create_company(TemplateView):
def get(self, request):
form = CompanyCreateForm()
title = "Some form"
return render(request, "form.html", {"form": form, "title": title})
def post(self, request):
form = CompanyCreateForm(request.POST)
if form.is_valid():
comp = form.save(commit=False)
comp.creator = request.user
comp.save()
return redirect('index')
The form is showing correctly also storing when I submit, the problem I am facing is with base.html where I show {% user.company %}; the form template extends it like:
{% extends "account/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
<form method="post" action="">
{% csrf_token %}
{{form|crispy}}
<button class="btn btn-success" type="submit">Save</button>
</form>
<br>
</div>
<br>
{% endblock %}
and in base.html I access
{% if user.is_authenticated %}
{% user.company %}
{% endif %}
But user.company is not showing even it is set; it shows only when I redirect to index but not when I render the form.
Can someone help me understand what causes this?
{% if request.user.is_authenticated %}
{% request.user.company %}
{% endif %}
you are not sending any context to the base.html, thus only user wont work.
This was the error when I simulated your code.
Error during template rendering
In template /home/user/django/drf_tutorial/snippets/templates/base.html, error at line 2
Invalid block tag on line 2: 'user.company', expected 'elif', 'else' or 'endif'. Did you forget to register or load this tag?
1 {% if user.is_authenticated %}
2 {% user.company %}
3 {% endif %}
4 {% block content %}{% endblock %}
It gives hint that the code to show company should be variable {{ }} instead of tag {% %}. So the base.html template should be as below.
{% if user.is_authenticated %}
{{ user.company }}
{% endif %}
{% block content %}{% endblock %}

Django: Query Selected Info in Model Within Class Based Views

I created some link with model-slug. But When I click my link, go to the page but return the empty value. I want to When I click any link, It will query value from the selected field like class_name or slug field.
this class list html page
{% extends "result/base.html" %}
{% block title %}Class List Name{% endblock title %} {% block content %}
<div class="row">
<div class="col-md-12 col-xs-offset-4">
<h2>Class List</h2>
{% for object in object_list %}
{{object.class_name}}
{% endfor %}
</div>
</div>
{% endblock %}
this is models.py file
class ClassName(models.Model):
class_name=models.CharField('Class Name', max_length=10)
class_added=models.DateTimeField(auto_now_add=True)
class_updated=models.DateTimeField(auto_now=True)
slug=models.SlugField(max_length=200, unique=True)
def __str__(self):
return self.class_name
this is views.py file
class ClassListView(ListView):
model=ClassName
slug_field = 'slug'
template_name='result/class_list.html'
class ClassDetailView(DetailView):
model=ClassName
slug_field = 'slug'
template_name='result/class_detail.html'
def get_context_data(self,*args, **kwargs):
context = super(ClassDetailView, self).get_context_data(*args,**kwargs)
context['class_wise_std'] = StudentInfo.objects.filter(
student_class_name__class_name__startswith=self.model.slug)
return context
this is class details html page
{% extends "result/base.html" %}
{% block title %}Class Detail's List{% endblock title %}
{% block content %}
<div class="row">
{% for object in class_wise_std %}
<div class="col-lg-12 col-sm-offset-4" style="margin:20px 10px">
<p>Name: {{object.student_name}}</p>
<p>Class: {{object.student_class_name}}</p>
<p>Father's Name: {{object.student_father_name}}</p>
<p>Mother's Name: {{object.student_mother_name}}</p>
<p>Roll: {{object.student_roll}}</p>
</div>
{% endfor %}
</div>
{% endblock content %}
this code
def get_context_data(self,*args, **kwargs):
context = super(ClassDetailView, self).get_context_data(*args,**kwargs)
context['class_wise_std'] = StudentInfo.objects.filter(
student_class_name__class_name__startswith=self.model.slug)
return context
I found this problem happen with this code. I want to filter with class_name field in ClassName Model.
StudentInfo.objects.filter(student_class_name__class_name__startswith=self.model.slug)
But I can successfully query my targeted info this way.
StudentInfo.objects.filter(student_class_name__class_name__startswith='One')
But It is not an efficient way. Now, How can I implement dynamically this?

Django Category Model and Template View Issue

My question is two phased but it's from the same Django Model. I am trying to get my Category model to work properly with my Petition model. Currently,
I get this 'FieldError' error when I define a queryset for my 'CategoryView' class:
Cannot resolve keyword 'created_on' into field. Choices are: description, id, petition, slug, title
Here is the code for the 'CategoryView' class:
class CategoryView(generic.ListView):
model = Category
template_name = 'petition/category.html'
context_object_name = 'category_list'
def get_queryset(self):
return Category.objects.order_by('-created_on')[:10]
Here is the code in my models.py:
class Category(models.Model):
title = models.CharField(max_length=90, default="Select an appropriate category")
slug = models.SlugField(max_length=200, unique=True)
description = models.TextField(null=False, blank=False)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.title
def get_absolute_url(self):
return "/categories/%s/"%self.slug
class Petition(models.Model):
title = models.CharField(max_length= 90, default="Enter petition title here")
created_on = models.DateTimeField(auto_now_add=True)
image = models.ImageField(null=False, upload_to=imageupload)
video = models.CharField(max_length=600, default="Enter an external video link")
petition = models.TextField(null=False, default="Type your petition here")
created_by = models.ForeignKey(User)
category = models.ManyToManyField(Category)
def total_likes(self):
return self.like_set.count()
def __str__(self):
return self.title[:50]
def get_signatures(self):
return self.signature_set.all()
I get the 'FieldError' on my category view template (category.html) when the 'get_queryset()' has been defined.
When I comment it out, the page displays but posts are not retrieved; I get a list of the categories instead. Here is my category view template(category.html):
{% include 'layout/header.html' %}
{% load humanize %}
<div class="container content">
<div class="row">
<div class="col-md-8 post-area">
{% if category_list %}
{% for petition in category_list %}
<div class="petition-block">
<h2 class="home-title">{{petition.title}}</h2>
<span class="petition-meta">
Created {{petition.created_on|naturaltime}} by
{% if petition.created_by == user %}
You
{% else %}
#{{ petition.created_by }}
{% endif %}
{% if petition.created_by == user %}
Edit
{% endif %}
{% if petition.created_by == user %}
Delete
{% endif %}
</span>
{% if petition.image %}
<img src="{{ petition.image.url }}" alt="petition image" class="img-responsive" />
{% endif %}
</div><!--//petition-block-->
{% endfor %}
{% else %}
<p>Sorry, there are no posts in the database</p>
{% endif %}
</div>
<div class="col-md-4">
<h3>Topics</h3>
<ul>
{% for petition in category_list %}
<li>{{petition.title}}</li>
{% endfor %}
</ul>
</div>
</body>
</html>
What am I doing wrong? Please help.
That's because you are trying to order the Category's queryset by created_on and your Category model doesn't have any field called created_on. That field is within Petition model. If you want to order the categories by petition's created_on you should do a "join" between tables, but with Django's ORM is easy.
For simplicity on your code is better to name the relation
class Petition(models.Model):
...
categories = models.ManyToManyField(Category, related_name='petitions')
...
Now you can refer to the category's petitions as 'petitions'
Category.objects.order_by('-petitions__created_on')
For use the petitions within the template the best way is prefetch the petitions on the queryset to avoid hitting the database every time in the for loop.
Category.objects.prefetch_related('petitions').order_by('-petitions__created_on')
That would bring every petition for each category. So in your template you can use:
{% for category in category_list %}
{% for petition in category.petitions.all %}
...
#{{ petition.created_by }}
...
{% end for %}
{% end for %}

Categories

Resources